diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 435201037d..4b173d25f2 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,28 +3,39 @@ "isRoot": true, "tools": { "jetbrains.resharper.globaltools": { - "version": "2024.1.4", + "version": "2024.3.6", "commands": [ "jb" - ] + ], + "rollForward": false }, "regitlint": { - "version": "6.3.12", + "version": "6.3.13", "commands": [ "regitlint" - ] + ], + "rollForward": false }, "dotnet-reportgenerator-globaltool": { - "version": "5.3.6", + "version": "5.4.5", "commands": [ "reportgenerator" - ] + ], + "rollForward": false }, "docfx": { - "version": "2.76.0", + "version": "2.78.2", "commands": [ "docfx" - ] + ], + "rollForward": false + }, + "microsoft.openapi.kiota": { + "version": "1.25.1", + "commands": [ + "kiota" + ], + "rollForward": false } } } \ No newline at end of file diff --git a/.editorconfig b/.editorconfig index 5a036d1797..2e5c1061b9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -4,60 +4,125 @@ root = true [*] indent_style = space indent_size = 4 +tab-width = 4 charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true -[*.{config,csproj,css,js,json,props,ruleset,xslt,html}] +[*.{config,csproj,css,js,json,props,targets,xml,ruleset,xsd,xslt,html,yml,yaml}] indent_size = 2 +tab-width = 2 +max_line_length = 160 + +[*.{cs,cshtml,ascx,aspx}] -[*.{cs}] #### C#/.NET Coding Conventions #### +# Default severity for IDE* analyzers with category 'Style' +# Note: specific rules below use severity silent, because Resharper code cleanup auto-fixes them. +dotnet_analyzer_diagnostic.category-Style.severity = warning + # 'using' directive preferences dotnet_sort_system_directives_first = true -csharp_using_directive_placement = outside_namespace:suggestion +csharp_using_directive_placement = outside_namespace:silent +# IDE0005: Remove unnecessary import +dotnet_diagnostic.IDE0005.severity = silent # Namespace declarations -csharp_style_namespace_declarations = file_scoped:suggestion +csharp_style_namespace_declarations = file_scoped:silent +# IDE0160: Use block-scoped namespace +dotnet_diagnostic.IDE0160.severity = silent +# IDE0161: Use file-scoped namespace +dotnet_diagnostic.IDE0161.severity = silent # this. preferences -dotnet_style_qualification_for_field = false:suggestion -dotnet_style_qualification_for_property = false:suggestion -dotnet_style_qualification_for_method = false:suggestion -dotnet_style_qualification_for_event = false:suggestion +dotnet_style_qualification_for_field = false:silent +dotnet_style_qualification_for_property = false:silent +dotnet_style_qualification_for_method = false:silent +dotnet_style_qualification_for_event = false:silent +# IDE0003: Remove this or Me qualification +dotnet_diagnostic.IDE0003.severity = silent +# IDE0009: Add this or Me qualification +dotnet_diagnostic.IDE0009.severity = silent # Language keywords vs BCL types preferences -dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion -dotnet_style_predefined_type_for_member_access = true:suggestion +dotnet_style_predefined_type_for_locals_parameters_members = true:silent +dotnet_style_predefined_type_for_member_access = true:silent +# IDE0049: Use language keywords instead of framework type names for type references +dotnet_diagnostic.IDE0049.severity = silent # Modifier preferences -dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion -csharp_preferred_modifier_order = public, private, protected, internal, new, static, abstract, virtual, sealed, readonly, override, extern, unsafe, volatile, async:suggestion -csharp_style_pattern_local_over_anonymous_function = false:silent +dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent +# IDE0040: Add accessibility modifiers +dotnet_diagnostic.IDE0040.severity = silent +csharp_preferred_modifier_order = public, private, protected, internal, new, static, abstract, virtual, sealed, readonly, override, extern, unsafe, volatile, async:silent +# IDE0036: Order modifiers +dotnet_diagnostic.IDE0036.severity = silent # Expression-level preferences dotnet_style_operator_placement_when_wrapping = end_of_line -dotnet_style_prefer_auto_properties = true:suggestion -dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion -dotnet_style_prefer_conditional_expression_over_return = true:suggestion -csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion +dotnet_style_prefer_auto_properties = true:silent +# IDE0032: Use auto property +dotnet_diagnostic.IDE0032.severity = silent +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +# IDE0045: Use conditional expression for assignment +dotnet_diagnostic.IDE0045.severity = silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +# IDE0046: Use conditional expression for return +dotnet_diagnostic.IDE0046.severity = silent +csharp_style_unused_value_expression_statement_preference = discard_variable:silent +# IDE0058: Remove unused expression value +dotnet_diagnostic.IDE0058.severity = silent + +# Collection expression preferences (note: partially turned off in Directory.Build.props) +dotnet_style_prefer_collection_expression = when_types_exactly_match # Parameter preferences -dotnet_code_quality_unused_parameters = non_public:suggestion +dotnet_code_quality_unused_parameters = non_public + +# Local functions vs lambdas +csharp_style_prefer_local_over_anonymous_function = false:silent +# IDE0039: Use local function instead of lambda +dotnet_diagnostic.IDE0039.severity = silent # Expression-bodied members -csharp_style_expression_bodied_accessors = true:suggestion -csharp_style_expression_bodied_constructors = false:suggestion -csharp_style_expression_bodied_indexers = true:suggestion -csharp_style_expression_bodied_lambdas = true:suggestion -csharp_style_expression_bodied_local_functions = false:suggestion -csharp_style_expression_bodied_methods = false:suggestion -csharp_style_expression_bodied_operators = false:suggestion -csharp_style_expression_bodied_properties = true:suggestion +csharp_style_expression_bodied_accessors = true:silent +# IDE0027: Use expression body for accessors +dotnet_diagnostic.IDE0027.severity = silent +csharp_style_expression_bodied_constructors = false:silent +# IDE0021: Use expression body for constructors +dotnet_diagnostic.IDE0021.severity = silent +csharp_style_expression_bodied_indexers = true:silent +# IDE0026: Use expression body for indexers +dotnet_diagnostic.IDE0026.severity = silent +csharp_style_expression_bodied_lambdas = true:silent +# IDE0053: Use expression body for lambdas +dotnet_diagnostic.IDE0053.severity = silent +csharp_style_expression_bodied_local_functions = false:silent +# IDE0061: Use expression body for local functions +dotnet_diagnostic.IDE0061.severity = silent +csharp_style_expression_bodied_methods = false:silent +# IDE0022: Use expression body for methods +dotnet_diagnostic.IDE0022.severity = silent +csharp_style_expression_bodied_operators = false:silent +# IDE0023: Use expression body for conversion operators +dotnet_diagnostic.IDE0023.severity = silent +# IDE0024: Use expression body for operators +dotnet_diagnostic.IDE0024.severity = silent +csharp_style_expression_bodied_properties = true:silent +# IDE0025: Use expression body for properties +dotnet_diagnostic.IDE0025.severity = silent + +# Member preferences (these analyzers are unreliable) +# IDE0051: Remove unused private member +dotnet_diagnostic.IDE0051.severity = silent +# IDE0052: Remove unread private member +dotnet_diagnostic.IDE0052.severity = silent # Code-block preferences -csharp_prefer_braces = true:suggestion +csharp_prefer_braces = true:silent +# IDE0011: Add braces +dotnet_diagnostic.IDE0011.severity = silent # Indentation preferences csharp_indent_case_contents_when_block = false @@ -66,19 +131,44 @@ csharp_indent_case_contents_when_block = false csharp_preserve_single_line_statements = false # 'var' usage preferences -csharp_style_var_for_built_in_types = false:none -csharp_style_var_when_type_is_apparent = true:none -csharp_style_var_elsewhere = false:none +csharp_style_var_for_built_in_types = false:silent +csharp_style_var_when_type_is_apparent = true:silent +csharp_style_var_elsewhere = false:silent +# IDE0007: Use var instead of explicit type +dotnet_diagnostic.IDE0007.severity = silent +# IDE0008: Use explicit type instead of var +dotnet_diagnostic.IDE0008.severity = silent # Parentheses preferences -dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:suggestion -dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:suggestion -dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:suggestion - -# Expression value is never used -dotnet_diagnostic.IDE0058.severity = none - -#### Naming Style #### +dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:silent +# IDE0047: Remove unnecessary parentheses +dotnet_diagnostic.IDE0047.severity = silent +# IDE0048: Add parentheses for clarity +dotnet_diagnostic.IDE0048.severity = silent + +# Switch preferences +# IDE0010: Add missing cases to switch statement +dotnet_diagnostic.IDE0010.severity = silent +# IDE0072: Add missing cases to switch expression +dotnet_diagnostic.IDE0072.severity = silent + +# Null check preferences +# IDE0029: Null check can be simplified +dotnet_diagnostic.IDE0029.severity = silent +# IDE0030: Null check can be simplified +dotnet_diagnostic.IDE0030.severity = silent +# IDE0270: Null check can be simplified +dotnet_diagnostic.IDE0270.severity = silent + +# JSON002: Probable JSON string detected +dotnet_diagnostic.JSON002.severity = silent + +# CA1062: Validate arguments of public methods +dotnet_code_quality.CA1062.excluded_symbol_names = Accept|DefaultVisit|Visit*|Apply* + +#### .NET Naming Style #### dotnet_diagnostic.IDE1006.severity = warning diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..0c78db34f3 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +# When running OpenAPI tests, these committed files are downloaded and written to disk (so we'll know when something changes). +# On Windows, these text files are auto-converted to crlf on git fetch, while the written downloaded files use lf line endings. +# Therefore, running the tests on Windows creates local changes. Staging them auto-converts back to crlf, which undoes the changes. +# To avoid this annoyance, the next line opts out of the auto-conversion and forces line endings to lf. +**/GeneratedSwagger/**/*.json text eol=lf diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index e7d3ce2494..14b5da9852 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -22,7 +22,7 @@ Bugs are tracked as [GitHub issues](https://github.com/json-api-dotnet/JsonApiDo Explain the problem and include additional details to help maintainers reproduce the problem: - **Use a clear and descriptive title** for the issue to identify the problem. -- **Describe the exact steps which reproduce the problem** in as many details as possible. When listing steps, don't just say what you did, but explain how you did it. +- **Describe the exact steps which reproduce the problem** in as many details as possible. When listing steps, don't just say what you did, but explain how you did it. - **Provide specific examples to demonstrate the steps.** Include links to files or GitHub projects, or copy/pasteable snippets, which you use in those examples. If you're providing snippets in the issue, use [Markdown code blocks](https://docs.github.com/en/github/writing-on-github/creating-and-highlighting-code-blocks). - **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior. Explain which behavior you expected to see instead and why. - **If you're reporting a crash**, include the full exception stack trace. diff --git a/.github/dependabot.yml b/.github/dependabot.yml index aa52764416..beb6e779ed 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,24 +1,24 @@ version: 2 updates: -- package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "weekly" - pull-request-branch-name: - separator: "-" -- package-ecosystem: nuget - directory: "/" - schedule: - interval: daily - pull-request-branch-name: - separator: "-" - open-pull-requests-limit: 25 - ignore: - # Block updates to all exposed dependencies of the NuGet packages we produce, as updating them would be a breaking change. - - dependency-name: 'Ben.Demystifier' - - dependency-name: 'Humanizer*' - - dependency-name: 'Microsoft.CodeAnalysis*' - - dependency-name: 'Microsoft.EntityFrameworkCore*' - # Block major updates of packages that require a matching .NET version. - - dependency-name: 'Microsoft.AspNetCore*' - update-types: ["version-update:semver-major"] + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + pull-request-branch-name: + separator: "-" + - package-ecosystem: nuget + directory: "/" + schedule: + interval: daily + pull-request-branch-name: + separator: "-" + open-pull-requests-limit: 25 + ignore: + # Block updates to all exposed dependencies of the NuGet packages we produce, as updating them would be a breaking change. + - dependency-name: "Ben.Demystifier" + - dependency-name: "Humanizer*" + - dependency-name: "Microsoft.CodeAnalysis*" + - dependency-name: "Microsoft.EntityFrameworkCore*" + # Block major updates of packages that require a matching .NET version. + - dependency-name: "Microsoft.AspNetCore*" + update-types: ["version-update:semver-major"] diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index da0993c185..7ee1333bd6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,7 +21,7 @@ concurrency: cancel-in-progress: true env: - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + DOTNET_NOLOGO: true DOTNET_CLI_TELEMETRY_OPTOUT: true jobs: @@ -46,8 +46,8 @@ jobs: uses: actions/setup-dotnet@v4 with: dotnet-version: | - 6.0.x - 8.0.x + 8.0.* + 9.0.* - name: Show installed versions shell: pwsh run: | @@ -72,14 +72,14 @@ jobs: $versionSuffix = $segments.Length -eq 1 ? '' : $segments[1..$($segments.Length - 1)] -join '-' [xml]$xml = Get-Content Directory.Build.props - $configuredVersionPrefix = $xml.Project.PropertyGroup.JsonApiDotNetCoreVersionPrefix | Select-Object -First 1 + $configuredVersionPrefix = $xml.Project.PropertyGroup.VersionPrefix | Select-Object -First 1 if ($configuredVersionPrefix -ne $versionPrefix) { Write-Error "Version prefix from git release tag '$versionPrefix' does not match version prefix '$configuredVersionPrefix' stored in Directory.Build.props." # To recover from this: # - Delete the GitHub release # - Run: git push --delete origin the-invalid-tag-name - # - Adjust JsonApiDotNetCoreVersionPrefix in Directory.Build.props, commit and push + # - Adjust VersionPrefix in Directory.Build.props, commit and push # - Recreate the GitHub release } } @@ -110,7 +110,7 @@ jobs: if: matrix.os == 'ubuntu-latest' env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 with: fail_ci_if_error: true verbose: true @@ -132,7 +132,7 @@ jobs: run: | cd docs & ./generate-examples.ps1 - dotnet docfx docfx.json + dotnet docfx docfx.json --warningsAsErrors true if ($LastExitCode -ne 0) { Write-Error "docfx failed with exit code $LastExitCode." } @@ -164,8 +164,8 @@ jobs: uses: actions/setup-dotnet@v4 with: dotnet-version: | - 6.0.x - 8.0.x + 8.0.* + 9.0.* - name: Git checkout uses: actions/checkout@v4 - name: Restore tools @@ -219,8 +219,8 @@ jobs: uses: actions/setup-dotnet@v4 with: dotnet-version: | - 6.0.x - 8.0.x + 8.0.* + 9.0.* - name: Git checkout uses: actions/checkout@v4 with: @@ -284,4 +284,4 @@ jobs: NUGET_ORG_API_KEY: ${{ secrets.NUGET_ORG_API_KEY }} shell: pwsh run: | - dotnet nuget push "$env:GITHUB_WORKSPACE/packages/*.nupkg" --api-key "$env:NUGET_ORG_API_KEY" --source 'nuget.org' + dotnet nuget push "$env:GITHUB_WORKSPACE/packages/*.nupkg" --api-key "$env:NUGET_ORG_API_KEY" --source 'nuget.org' --skip-duplicate diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index eb0375769e..508d210158 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -27,14 +27,17 @@ jobs: uses: actions/setup-dotnet@v4 with: dotnet-version: | - 6.0.x - 8.0.x + 8.0.* + 9.0.* - name: Git checkout uses: actions/checkout@v4 - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} + - name: Restore .NET tools + run: | + dotnet tool restore - name: Autobuild uses: github/codeql-action/autobuild@v3 - name: Perform CodeQL Analysis diff --git a/Build.ps1 b/Build.ps1 index 3abc926e6a..6c6ff9c13a 100644 --- a/Build.ps1 +++ b/Build.ps1 @@ -1,5 +1,3 @@ -$versionSuffix="pre" - function VerifySuccessExitCode { if ($LastExitCode -ne 0) { throw "Command failed with exit code $LastExitCode." @@ -16,14 +14,14 @@ Remove-Item -Recurse -Force * -Include coverage.cobertura.xml dotnet tool restore VerifySuccessExitCode -dotnet build --configuration Release /p:VersionSuffix=$versionSuffix +dotnet build --configuration Release VerifySuccessExitCode -dotnet test --no-build --configuration Release --collect:"XPlat Code Coverage" +dotnet test --no-build --configuration Release --verbosity quiet --collect:"XPlat Code Coverage" VerifySuccessExitCode dotnet reportgenerator -reports:**\coverage.cobertura.xml -targetdir:artifacts\coverage -filefilters:-*.g.cs VerifySuccessExitCode -dotnet pack --no-build --configuration Release --output artifacts/packages /p:VersionSuffix=$versionSuffix +dotnet pack --no-build --configuration Release --output artifacts/packages VerifySuccessExitCode diff --git a/CSharpGuidelinesAnalyzer.config b/CSharpGuidelinesAnalyzer.config index 89b568e155..6d5453159a 100644 --- a/CSharpGuidelinesAnalyzer.config +++ b/CSharpGuidelinesAnalyzer.config @@ -1,5 +1,5 @@ - + diff --git a/CodingGuidelines.ruleset b/CodingGuidelines.ruleset index e647ad9e58..b29d7423b4 100644 --- a/CodingGuidelines.ruleset +++ b/CodingGuidelines.ruleset @@ -1,32 +1,54 @@  - + + + - - - - - - + + - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Directory.Build.props b/Directory.Build.props index 860217f52e..05d57e58b4 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,4 +1,36 @@ + + enable + latest + enable + false + false + true + Recommended + $(MSBuildThisFileDirectory)CodingGuidelines.ruleset + $(MSBuildThisFileDirectory)tests.runsettings + 5.7.0 + pre + 1 + direct + $(NoWarn);NETSDK1215 + + + + + IDE0028;IDE0300;IDE0301;IDE0302;IDE0303;IDE0304;IDE0305;IDE0306 + $(NoWarn);$(UseCollectionExpressionRules) + + + $(NoWarn);NETSDK1215 + + $(NoWarn);AV2210 @@ -13,20 +45,18 @@ true + + $(NoWarn);CA1707;CA1062 + + + + $(NoWarn);CA1062 + + - + - - - enable - latest - enable - false - false - $(MSBuildThisFileDirectory)CodingGuidelines.ruleset - $(MSBuildThisFileDirectory)tests.runsettings - 5.6.0 - diff --git a/JsonApiDotNetCore.sln b/JsonApiDotNetCore.sln index c555610364..793c01950d 100644 --- a/JsonApiDotNetCore.sln +++ b/JsonApiDotNetCore.sln @@ -62,6 +62,24 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DapperExample", "src\Exampl EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DapperTests", "test\DapperTests\DapperTests.csproj", "{80E322F5-5F5D-4670-A30F-02D33C2C7900}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore.OpenApi.Swashbuckle", "src\JsonApiDotNetCore.OpenApi.Swashbuckle\JsonApiDotNetCore.OpenApi.Swashbuckle.csproj", "{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenApiTests", "test\OpenApiTests\OpenApiTests.csproj", "{B693DE14-BB28-496F-AB39-B4E674ABCA80}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore.OpenApi.Client.NSwag", "src\JsonApiDotNetCore.OpenApi.Client.NSwag\JsonApiDotNetCore.OpenApi.Client.NSwag.csproj", "{5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenApiNSwagClientExample", "src\Examples\OpenApiNSwagClientExample\OpenApiNSwagClientExample.csproj", "{7FC5DFA3-6F66-4FD8-820D-81E93856F252}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenApiNSwagClientTests", "test\OpenApiNSwagClientTests\OpenApiNSwagClientTests.csproj", "{77F98215-3085-422E-B99D-4C404C2114CF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenApiNSwagEndToEndTests", "test\OpenApiNSwagEndToEndTests\OpenApiNSwagEndToEndTests.csproj", "{3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore.OpenApi.Client.Kiota", "src\JsonApiDotNetCore.OpenApi.Client.Kiota\JsonApiDotNetCore.OpenApi.Client.Kiota.csproj", "{617FCA5D-A2DE-4083-B373-ADCA9901059F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenApiKiotaClientExample", "src\Examples\OpenApiKiotaClientExample\OpenApiKiotaClientExample.csproj", "{39DEAFE8-AE29-48E5-A67D-73776D70FC82}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenApiKiotaEndToEndTests", "test\OpenApiKiotaEndToEndTests\OpenApiKiotaEndToEndTests.csproj", "{FD86C676-3D80-4971-8D8C-B0729B2251F6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -312,6 +330,114 @@ Global {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Release|x64.Build.0 = Release|Any CPU {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Release|x86.ActiveCfg = Release|Any CPU {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Release|x86.Build.0 = Release|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|Any CPU.Build.0 = Debug|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x64.ActiveCfg = Debug|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x64.Build.0 = Debug|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x86.ActiveCfg = Debug|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x86.Build.0 = Debug|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|Any CPU.ActiveCfg = Release|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|Any CPU.Build.0 = Release|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x64.ActiveCfg = Release|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x64.Build.0 = Release|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x86.ActiveCfg = Release|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x86.Build.0 = Release|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x64.ActiveCfg = Debug|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x64.Build.0 = Debug|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x86.ActiveCfg = Debug|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x86.Build.0 = Debug|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|Any CPU.Build.0 = Release|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x64.ActiveCfg = Release|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x64.Build.0 = Release|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x86.ActiveCfg = Release|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x86.Build.0 = Release|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|x64.ActiveCfg = Debug|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|x64.Build.0 = Debug|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|x86.ActiveCfg = Debug|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|x86.Build.0 = Debug|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|Any CPU.Build.0 = Release|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|x64.ActiveCfg = Release|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|x64.Build.0 = Release|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|x86.ActiveCfg = Release|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|x86.Build.0 = Release|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|x64.ActiveCfg = Debug|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|x64.Build.0 = Debug|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|x86.ActiveCfg = Debug|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|x86.Build.0 = Debug|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|Any CPU.Build.0 = Release|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|x64.ActiveCfg = Release|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|x64.Build.0 = Release|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|x86.ActiveCfg = Release|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|x86.Build.0 = Release|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Debug|x64.ActiveCfg = Debug|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Debug|x64.Build.0 = Debug|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Debug|x86.ActiveCfg = Debug|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Debug|x86.Build.0 = Debug|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Release|Any CPU.Build.0 = Release|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Release|x64.ActiveCfg = Release|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Release|x64.Build.0 = Release|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Release|x86.ActiveCfg = Release|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Release|x86.Build.0 = Release|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Debug|x64.ActiveCfg = Debug|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Debug|x64.Build.0 = Debug|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Debug|x86.ActiveCfg = Debug|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Debug|x86.Build.0 = Debug|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Release|Any CPU.Build.0 = Release|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Release|x64.ActiveCfg = Release|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Release|x64.Build.0 = Release|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Release|x86.ActiveCfg = Release|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Release|x86.Build.0 = Release|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Debug|x64.ActiveCfg = Debug|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Debug|x64.Build.0 = Debug|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Debug|x86.ActiveCfg = Debug|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Debug|x86.Build.0 = Debug|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Release|Any CPU.Build.0 = Release|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Release|x64.ActiveCfg = Release|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Release|x64.Build.0 = Release|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Release|x86.ActiveCfg = Release|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Release|x86.Build.0 = Release|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Debug|Any CPU.Build.0 = Debug|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Debug|x64.ActiveCfg = Debug|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Debug|x64.Build.0 = Debug|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Debug|x86.ActiveCfg = Debug|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Debug|x86.Build.0 = Debug|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Release|Any CPU.ActiveCfg = Release|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Release|Any CPU.Build.0 = Release|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Release|x64.ActiveCfg = Release|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Release|x64.Build.0 = Release|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Release|x86.ActiveCfg = Release|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Release|x86.Build.0 = Release|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Debug|x64.ActiveCfg = Debug|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Debug|x64.Build.0 = Debug|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Debug|x86.ActiveCfg = Debug|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Debug|x86.Build.0 = Debug|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Release|Any CPU.Build.0 = Release|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Release|x64.ActiveCfg = Release|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Release|x64.Build.0 = Release|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Release|x86.ActiveCfg = Release|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -337,6 +463,15 @@ Global {24B0C12F-38CD-4245-8785-87BEFAD55B00} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} {C1774117-5073-4DF8-B5BE-BF7B538BD1C2} = {026FBC6C-AF76-4568-9B87-EC73457899FD} {80E322F5-5F5D-4670-A30F-02D33C2C7900} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF} + {B693DE14-BB28-496F-AB39-B4E674ABCA80} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF} + {7FC5DFA3-6F66-4FD8-820D-81E93856F252} = {026FBC6C-AF76-4568-9B87-EC73457899FD} + {77F98215-3085-422E-B99D-4C404C2114CF} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} + {617FCA5D-A2DE-4083-B373-ADCA9901059F} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF} + {39DEAFE8-AE29-48E5-A67D-73776D70FC82} = {026FBC6C-AF76-4568-9B87-EC73457899FD} + {FD86C676-3D80-4971-8D8C-B0729B2251F6} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {A2421882-8F0A-4905-928F-B550B192F9A4} diff --git a/JsonApiDotNetCore.sln.DotSettings b/JsonApiDotNetCore.sln.DotSettings index 399be60883..6c29a58aef 100644 --- a/JsonApiDotNetCore.sln.DotSettings +++ b/JsonApiDotNetCore.sln.DotSettings @@ -1,19 +1,12 @@  - // Use the following placeholders: -// $EXPR$ -- source expression -// $NAME$ -- source name (string literal or 'nameof' expression) -// $MESSAGE$ -- string literal in the form of "$NAME$ != null" -JsonApiDotNetCore.ArgumentGuard.NotNull($EXPR$); - 199 - 5000 - 99 - 100 - 200 - 1000 - 500 + 5000 + 2000 3000 - 50 False + True + 83FF097C-C8C6-477B-9FAB-DF99B84978B5/f:ReadOnlySet.cs + swagger.g.json + swagger.json SOLUTION True True @@ -81,6 +74,7 @@ JsonApiDotNetCore.ArgumentGuard.NotNull($EXPR$); SUGGESTION SUGGESTION WARNING + DO_NOT_SHOW WARNING WARNING WARNING @@ -99,6 +93,7 @@ JsonApiDotNetCore.ArgumentGuard.NotNull($EXPR$); WARNING True SUGGESTION + False <?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 @@ -137,6 +132,7 @@ JsonApiDotNetCore.ArgumentGuard.NotNull($EXPR$); NEVER False NEVER + False False False NEVER @@ -595,11 +591,12 @@ JsonApiDotNetCore.ArgumentGuard.NotNull($EXPR$); True True True + True True True True True - Replace argument null check using throw expression with Guard clause + Replace argument null check using throw expression with ArgumentNullException.ThrowIfNull True True False @@ -618,13 +615,12 @@ JsonApiDotNetCore.ArgumentGuard.NotNull($EXPR$); True CSHARP False - Replace argument null check with Guard clause - JsonApiDotNetCore.ArgumentGuard.NotNull($argument$); + System.ArgumentNullException.ThrowIfNull($argument$); $left$ = $right$; $left$ = $right$ ?? throw new ArgumentNullException(nameof($argument$)); WARNING True - Replace argument == null check with Guard clause + Replace argument == null check with ArgumentNullException.ThrowIfNull True True False @@ -633,8 +629,7 @@ $left$ = $right$; True CSHARP False - Replace argument null check with Guard clause - JsonApiDotNetCore.ArgumentGuard.NotNull($argument$); + System.ArgumentNullException.ThrowIfNull($argument$); if ($argument$ == null) throw new ArgumentNullException(nameof($argument$)); WARNING True @@ -646,12 +641,11 @@ $left$ = $right$; True CSHARP False - Replace collection null/empty check with extension method $collection$.IsNullOrEmpty() $collection$ == null || !$collection$.Any() WARNING True - Replace argument is null check with Guard clause + Replace argument is null check with ArgumentNullException.ThrowIfNull True True False @@ -660,15 +654,17 @@ $left$ = $right$; True CSHARP False - JsonApiDotNetCore.ArgumentGuard.NotNull($argument$); + System.ArgumentNullException.ThrowIfNull($argument$); if ($argument$ is null) throw new ArgumentNullException(nameof($argument$)); WARNING True + True True True True True True + True True True True diff --git a/PackageReadme.md b/PackageReadme.md index f57386041b..a6d0017f6a 100644 --- a/PackageReadme.md +++ b/PackageReadme.md @@ -1,4 +1,4 @@ -A framework for building [JSON:API](http://jsonapi.org/) compliant REST APIs using .NET Core and Entity Framework Core. Includes support for [Atomic Operations](https://jsonapi.org/ext/atomic/). +A framework for building [JSON:API](https://jsonapi.org/) compliant REST APIs using .NET Core and Entity Framework Core. Includes support for [Atomic Operations](https://jsonapi.org/ext/atomic/). The ultimate goal of this library is to eliminate as much boilerplate as possible by offering out-of-the-box features such as sorting, filtering and pagination. You just need to focus on defining the resources and implementing your custom business logic. This library has been designed around dependency injection, making extensibility incredibly easy. diff --git a/README.md b/README.md index 5ae9184e0c..d01f0b2dc7 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ # JsonApiDotNetCore -A framework for building [JSON:API](http://jsonapi.org/) compliant REST APIs using .NET Core and Entity Framework Core. Includes support for [Atomic Operations](https://jsonapi.org/ext/atomic/). +A framework for building [JSON:API](https://jsonapi.org/) compliant REST APIs using .NET Core and Entity Framework Core. Includes support for [Atomic Operations](https://jsonapi.org/ext/atomic/). [![Build](https://github.com/json-api-dotnet/JsonApiDotNetCore/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/json-api-dotnet/JsonApiDotNetCore/actions/workflows/build.yml?query=branch%3Amaster) [![Coverage](https://codecov.io/gh/json-api-dotnet/JsonApiDotNetCore/branch/master/graph/badge.svg?token=pn036tWV8T)](https://codecov.io/gh/json-api-dotnet/JsonApiDotNetCore) [![NuGet](https://img.shields.io/nuget/v/JsonApiDotNetCore.svg)](https://www.nuget.org/packages/JsonApiDotNetCore/) [![Chat](https://badges.gitter.im/json-api-dotnet-core/Lobby.svg)](https://gitter.im/json-api-dotnet-core/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![FIRST-TIMERS](https://img.shields.io/badge/first--timers--only-friendly-blue.svg)](http://www.firsttimersonly.com/) +[![FIRST-TIMERS](https://img.shields.io/badge/first--timers--only-friendly-blue.svg)](https://www.firsttimersonly.com/) The ultimate goal of this library is to eliminate as much boilerplate as possible by offering out-of-the-box features such as sorting, filtering and pagination. You just need to focus on defining the resources and implementing your custom business logic. This library has been designed around dependency injection, making extensibility incredibly easy. @@ -85,13 +85,10 @@ See also our [versioning policy](./VERSIONING_POLICY.md). | | | 7 | 7 | | 5.5+ | Stable | 6 | 6, 7 | | | | 7 | 7 | -| | | 8 | 8 | -| master | Preview | 6 | 6, 7 | -| | | 7 | 7 | -| | | 8 | 8 | -| openapi | Experimental | 6 | 6, 7 | -| | | 7 | 7 | -| | | 8 | 8 | +| | | 8 | 8, 9 | +| | | 9 | 9 | +| master | Preview | 8 | 8, 9 | +| | | 9 | 9 | ## Contributing @@ -110,7 +107,7 @@ To try it out, follow the steps below: In the command above: - Replace YOUR-GITHUB-USERNAME with the username you use to login your GitHub account. - Replace YOUR-PAT-CLASSIC with the token your created above. - + :warning: If the above command doesn't give you access in the next step, remove the package source by running: ```bash dotnet nuget remove source github-json-api diff --git a/ROADMAP.md b/ROADMAP.md index 7ba6a2a5a8..d73797824f 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -6,12 +6,14 @@ This document provides an overview of the direction this project is heading and We have an interest in the following topics. It's too soon yet to decide whether they'll make it into v5.x or in a later major version. -- OpenAPI (Swagger): Generate documentation and typed clients [#1046](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/1046) +- Provide additional OpenAPI support [#1046](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/1046) - Query strings on JSON-mapped columns [#1439](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/1439) +- Improved resource inheritance [#1642](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/1642) - Improved SQL Server support [#1118](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/1118) +- Use incremental source generator [#1447](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/1447) - Optimistic concurrency [#1119](https://github.com/json-api-dotnet/JsonApiDotNetCore/pull/1119) -- Fluent API [#776](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/776) - Idempotency [#1132](https://github.com/json-api-dotnet/JsonApiDotNetCore/pull/1132) +- Fluent API [#776](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/776) ## Feedback diff --git a/WarningSeverities.DotSettings b/WarningSeverities.DotSettings index 060df315df..5b64971520 100644 --- a/WarningSeverities.DotSettings +++ b/WarningSeverities.DotSettings @@ -1,4 +1,5 @@  + WARNING WARNING WARNING WARNING @@ -197,7 +198,6 @@ WARNING WARNING WARNING - WARNING WARNING WARNING WARNING diff --git a/benchmarks/Benchmarks.csproj b/benchmarks/Benchmarks.csproj index 9dbb9ba093..90d53461d2 100644 --- a/benchmarks/Benchmarks.csproj +++ b/benchmarks/Benchmarks.csproj @@ -1,7 +1,7 @@ Exe - net8.0 + net9.0 true diff --git a/benchmarks/Deserialization/DeserializationBenchmarkBase.cs b/benchmarks/Deserialization/DeserializationBenchmarkBase.cs index bbf746d1a8..4febabba1a 100644 --- a/benchmarks/Deserialization/DeserializationBenchmarkBase.cs +++ b/benchmarks/Deserialization/DeserializationBenchmarkBase.cs @@ -11,10 +11,12 @@ namespace Benchmarks.Deserialization; -public abstract class DeserializationBenchmarkBase +public abstract class DeserializationBenchmarkBase : IDisposable { - protected readonly JsonSerializerOptions SerializerReadOptions; - protected readonly DocumentAdapter DocumentAdapter; + private readonly ServiceContainer _serviceProvider = new(); + + protected JsonSerializerOptions SerializerReadOptions { get; } + protected DocumentAdapter DocumentAdapter { get; } protected DeserializationBenchmarkBase() { @@ -23,12 +25,11 @@ protected DeserializationBenchmarkBase() options.SerializerOptions.Converters.Add(new ResourceObjectConverter(resourceGraph)); SerializerReadOptions = ((IJsonApiOptions)options).SerializerReadOptions; - var serviceContainer = new ServiceContainer(); - var resourceFactory = new ResourceFactory(serviceContainer); - var resourceDefinitionAccessor = new ResourceDefinitionAccessor(resourceGraph, serviceContainer); + var resourceFactory = new ResourceFactory(_serviceProvider); + var resourceDefinitionAccessor = new ResourceDefinitionAccessor(resourceGraph, _serviceProvider); - serviceContainer.AddService(typeof(IResourceDefinitionAccessor), resourceDefinitionAccessor); - serviceContainer.AddService(typeof(IResourceDefinition), new JsonApiResourceDefinition(resourceGraph)); + _serviceProvider.AddService(typeof(IResourceDefinitionAccessor), resourceDefinitionAccessor); + _serviceProvider.AddService(typeof(IResourceDefinition), new JsonApiResourceDefinition(resourceGraph)); // ReSharper disable once VirtualMemberCallInConstructor JsonApiRequest request = CreateJsonApiRequest(resourceGraph); @@ -53,6 +54,22 @@ protected DeserializationBenchmarkBase() protected abstract JsonApiRequest CreateJsonApiRequest(IResourceGraph resourceGraph); + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + +#pragma warning disable CA1063 // Implement IDisposable Correctly + private void Dispose(bool disposing) +#pragma warning restore CA1063 // Implement IDisposable Correctly + { + if (disposing) + { + _serviceProvider.Dispose(); + } + } + [UsedImplicitly(ImplicitUseTargetFlags.Members)] public sealed class IncomingResource : Identifiable { diff --git a/benchmarks/Program.cs b/benchmarks/Program.cs index b1e3307931..04d5fa1eaa 100644 --- a/benchmarks/Program.cs +++ b/benchmarks/Program.cs @@ -3,20 +3,12 @@ using Benchmarks.QueryString; using Benchmarks.Serialization; -namespace Benchmarks; +var switcher = new BenchmarkSwitcher([ + typeof(ResourceDeserializationBenchmarks), + typeof(OperationsDeserializationBenchmarks), + typeof(ResourceSerializationBenchmarks), + typeof(OperationsSerializationBenchmarks), + typeof(QueryStringParserBenchmarks) +]); -internal static class Program -{ - private static void Main(string[] args) - { - var switcher = new BenchmarkSwitcher([ - typeof(ResourceDeserializationBenchmarks), - typeof(OperationsDeserializationBenchmarks), - typeof(ResourceSerializationBenchmarks), - typeof(OperationsSerializationBenchmarks), - typeof(QueryStringParserBenchmarks) - ]); - - switcher.Run(args); - } -} +switcher.Run(args); diff --git a/benchmarks/QueryString/QueryStringParserBenchmarks.cs b/benchmarks/QueryString/QueryStringParserBenchmarks.cs index 0b2f88134a..5e5a65ed9f 100644 --- a/benchmarks/QueryString/QueryStringParserBenchmarks.cs +++ b/benchmarks/QueryString/QueryStringParserBenchmarks.cs @@ -14,8 +14,9 @@ namespace Benchmarks.QueryString; [MarkdownExporter] [SimpleJob(3, 10, 20)] [MemoryDiagnoser] -public class QueryStringParserBenchmarks +public class QueryStringParserBenchmarks : IDisposable { + private readonly ServiceContainer _serviceProvider = new(); private readonly FakeRequestQueryStringAccessor _queryStringAccessor = new(); private readonly QueryStringReader _queryStringReader; @@ -30,11 +31,11 @@ public QueryStringParserBenchmarks() var request = new JsonApiRequest { - PrimaryResourceType = resourceGraph.GetResourceType(typeof(QueryableResource)), + PrimaryResourceType = resourceGraph.GetResourceType(), IsCollection = true }; - var resourceFactory = new ResourceFactory(new ServiceContainer()); + var resourceFactory = new ResourceFactory(_serviceProvider); var includeParser = new IncludeParser(options); var includeReader = new IncludeQueryStringParameterReader(includeParser, request, resourceGraph); @@ -92,4 +93,20 @@ public void ComplexQuery() _queryStringAccessor.SetQueryString(queryString); _queryStringReader.ReadAll(null); } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + +#pragma warning disable CA1063 // Implement IDisposable Correctly + private void Dispose(bool disposing) +#pragma warning restore CA1063 // Implement IDisposable Correctly + { + if (disposing) + { + _serviceProvider.Dispose(); + } + } } diff --git a/benchmarks/Serialization/OperationsSerializationBenchmarks.cs b/benchmarks/Serialization/OperationsSerializationBenchmarks.cs index 458c4eecae..8c4a00b6da 100644 --- a/benchmarks/Serialization/OperationsSerializationBenchmarks.cs +++ b/benchmarks/Serialization/OperationsSerializationBenchmarks.cs @@ -13,7 +13,7 @@ namespace Benchmarks.Serialization; // ReSharper disable once ClassCanBeSealed.Global public class OperationsSerializationBenchmarks : SerializationBenchmarkBase { - private readonly IEnumerable _responseOperations; + private readonly List _responseOperations; public OperationsSerializationBenchmarks() { @@ -23,7 +23,7 @@ public OperationsSerializationBenchmarks() _responseOperations = CreateResponseOperations(request); } - private static IEnumerable CreateResponseOperations(IJsonApiRequest request) + private static List CreateResponseOperations(IJsonApiRequest request) { var resource1 = new OutgoingResource { @@ -102,14 +102,14 @@ private static IEnumerable CreateResponseOperations(IJsonApi var targetedFields = new TargetedFields(); - return new List - { - new(resource1, targetedFields, request), - new(resource2, targetedFields, request), - new(resource3, targetedFields, request), - new(resource4, targetedFields, request), - new(resource5, targetedFields, request) - }; + return + [ + new OperationContainer(resource1, targetedFields, request), + new OperationContainer(resource2, targetedFields, request), + new OperationContainer(resource3, targetedFields, request), + new OperationContainer(resource4, targetedFields, request), + new OperationContainer(resource5, targetedFields, request) + ]; } [Benchmark] diff --git a/benchmarks/Serialization/ResourceSerializationBenchmarks.cs b/benchmarks/Serialization/ResourceSerializationBenchmarks.cs index a2d76b87b1..6f979e86b9 100644 --- a/benchmarks/Serialization/ResourceSerializationBenchmarks.cs +++ b/benchmarks/Serialization/ResourceSerializationBenchmarks.cs @@ -1,7 +1,6 @@ using System.Collections.Immutable; using System.Text.Json; using BenchmarkDotNet.Attributes; -using JsonApiDotNetCore; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Middleware; using JsonApiDotNetCore.Queries; @@ -97,12 +96,17 @@ private static OutgoingResource CreateResponseResource() resource1.Single2 = resource2; resource2.Single3 = resource3; - resource3.Multi4 = resource4.AsHashSet(); - resource4.Multi5 = resource5.AsHashSet(); + resource3.Multi4 = ToHashSet(resource4); + resource4.Multi5 = ToHashSet(resource5); return resource1; } + private static HashSet ToHashSet(T element) + { + return [element]; + } + [Benchmark] public string SerializeResourceResponse() { diff --git a/benchmarks/Serialization/SerializationBenchmarkBase.cs b/benchmarks/Serialization/SerializationBenchmarkBase.cs index eba222c9d1..c8451835cc 100644 --- a/benchmarks/Serialization/SerializationBenchmarkBase.cs +++ b/benchmarks/Serialization/SerializationBenchmarkBase.cs @@ -14,9 +14,9 @@ namespace Benchmarks.Serialization; public abstract class SerializationBenchmarkBase { - protected readonly JsonSerializerOptions SerializerWriteOptions; - protected readonly IResponseModelAdapter ResponseModelAdapter; - protected readonly IResourceGraph ResourceGraph; + protected JsonSerializerOptions SerializerWriteOptions { get; } + protected IResponseModelAdapter ResponseModelAdapter { get; } + protected IResourceGraph ResourceGraph { get; } protected SerializationBenchmarkBase() { diff --git a/docs/build-dev.ps1 b/docs/build-dev.ps1 index d65826687a..6345875fc7 100644 --- a/docs/build-dev.ps1 +++ b/docs/build-dev.ps1 @@ -40,7 +40,7 @@ if (-Not $NoBuild -Or -Not (Test-Path -Path _site)) { dotnet tool restore VerifySuccessExitCode -dotnet docfx ./docfx.json +dotnet docfx ./docfx.json --warningsAsErrors true VerifySuccessExitCode Copy-Item -Force home/*.html _site/ diff --git a/docs/docfx.json b/docs/docfx.json index eb94da412e..232d8768eb 100644 --- a/docs/docfx.json +++ b/docs/docfx.json @@ -1,53 +1,68 @@ { - "metadata": [ + "metadata": [ + { + "properties": { + "ProduceReferenceAssembly": "true" + }, + "src": [ { - "src": [ - { - "files": [ "**/JsonApiDotNetCore.csproj","**/JsonApiDotNetCore.Annotations.csproj" ], - "src": "../" - } - ], - "dest": "api", - "disableGitFeatures": false + "files": [ + "**/JsonApiDotNetCore.csproj", + "**/JsonApiDotNetCore.Annotations.csproj" + ], + "src": "../" } - ], - "build": { - "content": [ - { - "files": [ - "api/**.yml", - "api/index.md", - "getting-started/**.md", - "getting-started/**/toc.yml", - "usage/**.md", - "request-examples/**.md", - "internals/**.md", - "toc.yml", - "*.md" - ], - "exclude": [ - "**/README.md" - ] - } - ], - "resource": [ - { - "files": [ "diagrams/*.svg" ] - } - ], - "overwrite": [ - { - "exclude": [ "obj/**", "_site/**" ] - } - ], - "dest": "_site", - "globalMetadataFiles": [], - "fileMetadataFiles": [], - "template": [ "default", "modern" ], - "postProcessors": [], - "noLangKeyword": false, - "keepFileLink": false, - "cleanupCacheHistory": false, - "disableGitFeatures": false + ], + "dest": "api", + "disableGitFeatures": false } + ], + "build": { + "content": [ + { + "files": [ + "api/**.yml", + "api/index.md", + "ext/openapi/index.md", + "getting-started/**.md", + "getting-started/**/toc.yml", + "usage/**.md", + "request-examples/**.md", + "internals/**.md", + "toc.yml", + "*.md" + ], + "exclude": [ + "**/README.md" + ] + } + ], + "resource": [ + { + "files": [ + "diagrams/*.svg" + ] + } + ], + "overwrite": [ + { + "exclude": [ + "obj/**", + "_site/**" + ] + } + ], + "dest": "_site", + "globalMetadataFiles": [], + "fileMetadataFiles": [], + "template": [ + "default", + "modern" + ], + "postProcessors": [], + "noLangKeyword": false, + "keepFileLink": false, + "cleanupCacheHistory": false, + "disableGitFeatures": false + } } diff --git a/docs/ext/openapi/index.md b/docs/ext/openapi/index.md new file mode 100644 index 0000000000..20aad7b305 --- /dev/null +++ b/docs/ext/openapi/index.md @@ -0,0 +1,127 @@ +# JSON:API Extension for OpenAPI + +This extension facilitates using OpenAPI client generators targeting JSON:API documents. + +In JSON:API, a resource object contains the `type` member, which defines the structure of nested [attributes](https://jsonapi.org/format/#document-resource-object-attributes) and [relationships](https://jsonapi.org/format/#document-resource-object-relationships) objects. +While OpenAPI supports such constraints using `allOf` inheritance with a discriminator property for the `data` member, +it provides no way to express that the discriminator recursively applies to nested objects. + +This extension addresses that limitation by defining additional discriminator properties to guide code generation tools. + +## URI + +This extension has the URI `https://www.jsonapi.net/ext/openapi`. +Because code generators often choke on the double quotes in `Accept` and `Content-Type` HTTP header values, a relaxed form is also permitted: `openapi`. + +For example, the following `Content-Type` header: + +```http +Content-Type: application/vnd.api+json; ext="https://www.jsonapi.net/ext/openapi" +``` + +is equivalent to: + +```http +Content-Type: application/vnd.api+json; ext=openapi +``` + +To avoid the need for double quotes when multiple extensions are used, the following relaxed form can be used: + +```http +Content-Type: application/vnd.api+json; ext=openapi; ext=atomic +``` + +> [!NOTE] +> The [base specification](https://jsonapi.org/format/#media-type-parameter-rules) *forbids* the use of multiple `ext` parameters +> and *requires* that each extension name must be a URI. +> This extension relaxes both constraints for practical reasons, to workaround bugs in client generators that produce broken code otherwise. + +## Namespace + +This extension uses the namespace `openapi`. + +> [!NOTE] +> JSON:API extensions can only introduce new document members using a reserved namespace as a prefix. + +## Document Structure + +A document that supports this extension MAY include any of the top-level members allowed by the base specification, +including any members defined in the [Atomic Operations extension](https://jsonapi.org/ext/atomic/). + +### Resource Objects + +In addition to the members allowed by the base specification, the following member MAY be included +in [attributes](https://jsonapi.org/format/#document-resource-object-attributes) and [relationships](https://jsonapi.org/format/#document-resource-object-relationships) objects: + +* `openapi:discriminator` - A string that MUST be identical to the `type` member in the containing [resource object](https://jsonapi.org/format/#document-resource-objects). + +Here's how an article (i.e. a resource of type "articles") might appear in a document: + +```json +{ + "data": { + "type": "articles", + "id": "1", + "attributes": { + "openapi:discriminator": "articles", + "title": "Rails is Omakase" + }, + "relationships": { + "openapi:discriminator": "articles", + "author": { + "data": { "type": "people", "id": "9" } + } + } + } +} +``` + +### Atomic Operations + +In addition to the members allowed by the [Atomic Operations extension](https://jsonapi.org/ext/atomic/), +the following member MAY be included in elements of an `atomic:operations` array: + +* `openapi:discriminator` - A free-format string to facilitate generation of client code. + +For example: + +```http +POST /operations HTTP/1.1 +Host: example.org +Content-Type: application/vnd.api+json; ext="https://www.jsonapi.net/ext/openapi https://jsonapi.org/ext/atomic" +Accept: application/vnd.api+json; ext="https://www.jsonapi.net/ext/openapi https://jsonapi.org/ext/atomic" + +{ + "atomic:operations": [{ + "openapi:discriminator": "add-article", + "op": "add", + "data": { + "type": "articles", + "attributes": { + "openapi:discriminator": "articles", + "title": "JSON API paints my bikeshed!" + } + } + }] +} +``` + +## Processing + +A server MAY ignore the `openapi:discriminator` member in [attributes](https://jsonapi.org/format/#document-resource-object-attributes) and [relationships](https://jsonapi.org/format/#document-resource-object-relationships) objects from incoming requests. +A server SHOULD ignore the `openapi:discriminator` member in elements of an `atomic:operations` array. + +A server MUST include the `openapi:discriminator` member in [attributes](https://jsonapi.org/format/#document-resource-object-attributes) and [relationships](https://jsonapi.org/format/#document-resource-object-relationships) objects in outgoing responses. +The member value MUST be the same as the `type` member value of the containing resource object. + +A client MAY include the `openapi:discriminator` member in [attributes](https://jsonapi.org/format/#document-resource-object-attributes) and [relationships](https://jsonapi.org/format/#document-resource-object-relationships) objects in outgoing requests. +The member value MUST be the same as the `type` member value of the containing resource object. + +A client MAY include the `openapi:discriminator` member in elements of an `atomic:operations` array. + +### Processing Errors + +A server SHOULD validate that the value of the `openapi:discriminator` member in +[attributes](https://jsonapi.org/format/#document-resource-object-attributes) and [relationships](https://jsonapi.org/format/#document-resource-object-relationships) objects +is identical to the `type` member in the containing resource object. When validation fails, the server MUST respond with a `409 Conflict` +and SHOULD include a document with a top-level `errors` member that contains an error object. diff --git a/docs/getting-started/faq.md b/docs/getting-started/faq.md index 57f1258c24..54b4e50d52 100644 --- a/docs/getting-started/faq.md +++ b/docs/getting-started/faq.md @@ -4,10 +4,11 @@ While the [documentation](~/usage/resources/index.md) covers basic features and a few runnable example projects are available [here](https://github.com/json-api-dotnet/JsonApiDotNetCore/tree/master/src/Examples), many more advanced use cases are available as integration tests [here](https://github.com/json-api-dotnet/JsonApiDotNetCore/tree/master/test/JsonApiDotNetCoreTests/IntegrationTests), so be sure to check them out! -#### Why can't I use OpenAPI? -Due to the mismatch between the JSON:API structure and the shape of ASP.NET controller methods, this does not work out of the box. -This is high on our agenda and we're steadily making progress, but it's quite complex and far from complete. -See [here](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/1046) for the current status, which includes instructions on trying out the latest build. +#### Why don't you use the built-in OpenAPI support in ASP.NET Core? +The structure of JSON:API request and response bodies differs significantly from the signature of JsonApiDotNetCore controllers. +JsonApiDotNetCore provides OpenAPI support using [Swashbuckle](https://github.com/domaindrivendev/Swashbuckle.AspNetCore), a mature and feature-rich library that is highly extensible. +The [OpenAPI support in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/openapi/overview) is still very young +and doesn't provide the level of extensibility needed for JsonApiDotNetCore. #### What's available to implement a JSON:API client? It depends on the programming language used. There's an overwhelming list of client libraries at https://jsonapi.org/implementations/#client-libraries. @@ -71,7 +72,7 @@ For example, if your primary key column is named "CustomerId" instead of "Id": builder.Entity().Property(x => x.Id).HasColumnName("CustomerId"); ``` -It certainly pays off to read up on these capabilities at [Creating and Configuring a Model](https://learn.microsoft.com/en-us/ef/core/modeling/). +It certainly pays off to read up on these capabilities at [Creating and Configuring a Model](https://learn.microsoft.com/ef/core/modeling/). Another great resource is [Learn Entity Framework Core](https://www.learnentityframeworkcore.com/configuration). #### Can I share my resource models with .NET Framework projects? @@ -80,7 +81,7 @@ This package contains just the JSON:API attributes and targets NetStandard 1.0, At startup, use [Auto-discovery](~/usage/resource-graph.md#auto-discovery) and point it to your shared project. #### What's the best place to put my custom business/validation logic? -For basic input validation, use the attributes from [ASP.NET ModelState Validation](https://learn.microsoft.com/en-us/aspnet/core/mvc/models/validation?source=recommendations&view=aspnetcore-7.0#built-in-attributes) to get the best experience. +For basic input validation, use the attributes from [ASP.NET ModelState Validation](https://learn.microsoft.com/aspnet/core/mvc/models/validation?source=recommendations&view=aspnetcore-7.0#built-in-attributes) to get the best experience. JsonApiDotNetCore is aware of them and adjusts behavior accordingly. And it produces the best possible error responses. For non-trivial business rules that require custom code, the place to be is [Resource Definitions](~/usage/extensibility/resource-definitions.md). @@ -148,7 +149,7 @@ And most resource definition callbacks are handled. That's because the built-in resource service translates all JSON:API query aspects of the request into a database-agnostic data structure called `QueryLayer`. Now the hard part for you becomes reading that data structure and producing data access calls from that. If your data store provides a LINQ provider, you can probably reuse [QueryableBuilder](https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/master/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryableBuilder.cs), -which drives the translation into [System.Linq.Expressions](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/expression-trees/). +which drives the translation into [System.Linq.Expressions](https://learn.microsoft.com/dotnet/csharp/programming-guide/concepts/expression-trees/). Note however, that it also produces calls to `.Include("")`, which is an Entity Framework Core-specific extension method, so you'll need to [prevent that from happening](https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/master/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryLayerIncludeConverter.cs). diff --git a/docs/usage/caching.md b/docs/usage/caching.md index 537ec70e4b..28d6a6a36e 100644 --- a/docs/usage/caching.md +++ b/docs/usage/caching.md @@ -2,7 +2,7 @@ _since v4.2_ -GET requests return an [ETag](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) HTTP header, which can be used by the client in subsequent requests to save network bandwidth. +GET requests return an [ETag](https://developer.mozilla.org/docs/Web/HTTP/Headers/ETag) HTTP header, which can be used by the client in subsequent requests to save network bandwidth. Be aware that the returned ETag represents the entire response body (a 'resource' in HTTP terminology) for a request URL that includes the query string. This is unrelated to JSON:API resources. Therefore, we do not use ETags for optimistic concurrency. diff --git a/docs/usage/common-pitfalls.md b/docs/usage/common-pitfalls.md index f1f3fed3d6..60162cfd37 100644 --- a/docs/usage/common-pitfalls.md +++ b/docs/usage/common-pitfalls.md @@ -50,7 +50,7 @@ Did you notice the missing type of the `LoginAccount.Customer` property? We must This is only one of the issues you'll run into. Just don't go there. The right way to model this is by having only `Customer` instead of `WebCustomer` and `AdminCustomer`. And then: -- Hide the `CreditRating` property for web users using [this](https://www.jsonapi.net/usage/extensibility/resource-definitions.html#excluding-fields) approach. +- Hide the `CreditRating` property for web users using [this](~/usage/extensibility/resource-definitions.md#excluding-fields) approach. - Block web users from setting the `CreditRating` property from POST/PATCH resource endpoints by either: - Detecting if the `CreditRating` property has changed, such as done [here](https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/master/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/RequestBody/WorkflowDefinition.cs). - Injecting `ITargetedFields`, throwing an error when it contains the `CreditRating` property. @@ -61,7 +61,7 @@ This paradigm [doesn't work well](https://github.com/json-api-dotnet/JsonApiDotN So if your API needs to guard invariants such as "the sum of all orders must never exceed 500 dollars", then you're better off with an RPC-style API instead of the REST paradigm that JSON:API follows. Adding constructors to resource classes that validate incoming parameters before assigning them to properties does not work. -Entity Framework Core [supports](https://learn.microsoft.com/en-us/ef/core/modeling/constructors#binding-to-mapped-properties) that, +Entity Framework Core [supports](https://learn.microsoft.com/ef/core/modeling/constructors#binding-to-mapped-properties) that, but does so via internal implementation details that are inaccessible by JsonApiDotNetCore. In JsonApiDotNetCore, resources are what DDD calls [anemic models](https://thedomaindrivendesign.io/anemic-model/). @@ -84,9 +84,14 @@ With stored procedures, you're either going to have a lot of work to do, or you' Neither sounds very compelling. If stored procedures is what you need, you're better off creating an RPC-style API that doesn't use JsonApiDotNetCore. #### Do not use `[ApiController]` on JSON:API controllers -Although recommended by Microsoft for hard-written controllers, the opinionated behavior of [`[ApiController]`](https://learn.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-7.0#apicontroller-attribute) violates the JSON:API specification. +Although recommended by Microsoft for hard-written controllers, the opinionated behavior of [`[ApiController]`](https://learn.microsoft.com/aspnet/core/web-api/#apicontroller-attribute) violates the JSON:API specification. Despite JsonApiDotNetCore trying its best to deal with it, the experience won't be as good as leaving it out. +#### Don't use auto-generated controllers with shared models + +When model classes are defined in a separate project, the controllers are generated in that project as well, which is probably not what you want. +For details, see [here](~/usage/extensibility/controllers.md#auto-generated-controllers). + #### Register/override injectable services Register your JSON:API resource services, resource definitions and repositories with `services.AddResourceService/AddResourceDefinition/AddResourceRepository()` instead of `services.AddScoped()`. When using [Auto-discovery](~/usage/resource-graph.md#auto-discovery), you don't need to register these at all. @@ -102,7 +107,7 @@ If you're in need of a quick setup, use [SQLite](https://www.sqlite.org/). After builder.Services.AddSqlite("Data Source=temp.db"); ``` Which creates `temp.db` on disk. Simply deleting the file gives you a clean slate. -This is a lot more convenient compared to using [SqlLocalDB](https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/sql-server-express-localdb), which runs a background service that breaks if you delete its underlying storage files. +This is a lot more convenient compared to using [SqlLocalDB](https://learn.microsoft.com/sql/database-engine/configure-windows/sql-server-express-localdb), which runs a background service that breaks if you delete its underlying storage files. However, even SQLite does not support all queries produced by Entity Framework Core. You'll get the best (and fastest) experience with [PostgreSQL in a docker container](https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/master/run-docker-postgres.ps1). @@ -140,6 +145,6 @@ If you need such side effects, it's easiest to inject your `DbContext` in the co A better way is to inject your `DbContext` in a [Resource Definition](~/usage/extensibility/resource-definitions.md) and apply the changes there. #### Concurrency tokens (timestamp/rowversion/xmin) won't work -While we'd love to support such [tokens for optimistic concurrency](https://learn.microsoft.com/en-us/ef/core/saving/concurrency?tabs=data-annotations), +While we'd love to support such [tokens for optimistic concurrency](https://learn.microsoft.com/ef/core/saving/concurrency), it turns out that the implementation is far from trivial. We've come a long way, but aren't sure how it should work when relationship endpoints and atomic operations are involved. If you're interested, we welcome your feedback at https://github.com/json-api-dotnet/JsonApiDotNetCore/pull/1119. diff --git a/docs/usage/extensibility/controllers.md b/docs/usage/extensibility/controllers.md index 68e1d86ea3..254b305ed9 100644 --- a/docs/usage/extensibility/controllers.md +++ b/docs/usage/extensibility/controllers.md @@ -6,7 +6,7 @@ To expose API endpoints, ASP.NET controllers need to be defined. _since v5_ -Controllers are auto-generated (using [source generators](https://docs.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview)) when you add `[Resource]` on your model class: +Controllers are auto-generated (using [source generators](https://learn.microsoft.com/dotnet/csharp/roslyn-sdk/#source-generators)) when you add `[Resource]` on your model class: ```c# [Resource] // Generates ArticlesController.g.cs diff --git a/docs/usage/extensibility/middleware.md b/docs/usage/extensibility/middleware.md index 62528893d3..dbbe81699f 100644 --- a/docs/usage/extensibility/middleware.md +++ b/docs/usage/extensibility/middleware.md @@ -3,9 +3,9 @@ The default middleware validates incoming `Content-Type` and `Accept` HTTP headers. Based on routing configuration, it fills `IJsonApiRequest`, an injectable object that contains JSON:API-related information about the request being processed. -It is possible to replace the built-in middleware components by configuring the IoC container and by configuring `MvcOptions`. +It is possible to replace the built-in middleware components by configuring the IoC container and by configuring `MvcOptions`. -## Configuring the IoC container +## Configuring the IoC container The following example replaces the internal exception filter with a custom implementation. diff --git a/docs/usage/extensibility/resource-definitions.md b/docs/usage/extensibility/resource-definitions.md index cf5400b722..644d43fb75 100644 --- a/docs/usage/extensibility/resource-definitions.md +++ b/docs/usage/extensibility/resource-definitions.md @@ -29,7 +29,7 @@ For various reasons (see examples below) you may need to change parts of the que `JsonApiResourceDefinition` (which is an empty implementation of `IResourceDefinition`) provides overridable methods that pass you the result of query string parameter parsing. The value returned by you determines what will be used to execute the query. -An intermediate format (`QueryExpression` and derived types) is used, which enables us to separate JSON:API implementation +An intermediate format (`QueryExpression` and derived types) is used, which enables us to separate JSON:API implementation from Entity Framework Core `IQueryable` execution. ### Excluding fields @@ -220,7 +220,7 @@ You can define additional query string parameters with the LINQ expression that If the key is present in a query string, the supplied LINQ expression will be added to the database query. > [!NOTE] -> This directly influences the Entity Framework Core `IQueryable`. As opposed to using `OnApplyFilter`, this enables the full range of Entity Framework Core operators. +> This directly influences the Entity Framework Core `IQueryable`. As opposed to using `OnApplyFilter`, this enables the full range of Entity Framework Core operators. But it only works on primary resource endpoints (for example: /articles, but not on /blogs/1/articles or /blogs?include=articles). ```c# diff --git a/docs/usage/openapi-client.md b/docs/usage/openapi-client.md new file mode 100644 index 0000000000..c0717d47ca --- /dev/null +++ b/docs/usage/openapi-client.md @@ -0,0 +1,356 @@ +> [!WARNING] +> OpenAPI support for JSON:API is currently experimental. The API and the structure of the OpenAPI document may change in future versions. + +# OpenAPI clients + +After [enabling OpenAPI](~/usage/openapi.md), you can generate a typed JSON:API client for your API in various programming languages. + +> [!NOTE] +> If you prefer a generic JSON:API client instead of a typed one, choose from the existing +> [client libraries](https://jsonapi.org/implementations/#client-libraries). + +The following code generators are supported, though you may try others as well: +- [NSwag](https://github.com/RicoSuter/NSwag) (v14.1 or higher): Produces clients for C# (requires `Newtonsoft.Json`) and TypeScript +- [Kiota](https://learn.microsoft.com/openapi/kiota/overview): Produces clients for C#, Go, Java, PHP, Python, Ruby, Swift and TypeScript + +# [NSwag](#tab/nswag) + +For C# clients, we provide an additional package that provides workarounds for bugs in NSwag and enables using partial POST/PATCH requests. + +To add it to your project, run the following command: +``` +dotnet add package JsonApiDotNetCore.OpenApi.Client.NSwag +``` + +# [Kiota](#tab/kiota) + +For C# clients, we provide an additional package that provides workarounds for bugs in Kiota, as well as MSBuild integration. + +To add it to your project, run the following command: +``` +dotnet add package JsonApiDotNetCore.OpenApi.Client.Kiota +``` + +--- + +## Getting started + +To generate your C# client, follow the steps below. + +# [NSwag](#tab/nswag) + +### Visual Studio + +The easiest way to get started is by using the built-in capabilities of Visual Studio. +The following steps describe how to generate and use a JSON:API client in C#, combined with our NuGet package. + +1. In **Solution Explorer**, right-click your client project, select **Add** > **Service Reference** and choose **OpenAPI**. + +1. On the next page, specify the OpenAPI URL to your JSON:API server, for example: `http://localhost:14140/swagger/v1/swagger.json`. + Specify `ExampleApiClient` as the class name, optionally provide a namespace and click **Finish**. + Visual Studio now downloads your swagger.json and updates your project file. + This adds a pre-build step that generates the client code. + + > [!TIP] + > To later re-download swagger.json and regenerate the client code, + > right-click **Dependencies** > **Manage Connected Services** and click the **Refresh** icon. + +1. Run package update now, which fixes incompatibilities and bugs from older versions. + +1. Add our client package to your project: + + ``` + dotnet add package JsonApiDotNetCore.OpenApi.Client.NSwag + ``` + +1. Add code that calls one of your JSON:API endpoints. + + ```c# + using var httpClient = new HttpClient(); + var apiClient = new ExampleApiClient(httpClient); + + var getResponse = await apiClient.GetPersonCollectionAsync(new Dictionary + { + ["filter"] = "has(assignedTodoItems)", + ["sort"] = "-lastName", + ["page[size]"] = "5" + }); + + foreach (var person in getResponse.Data) + { + Console.WriteLine($"Found person {person.Id}: {person.Attributes!.DisplayName}"); + } + ``` + +1. Extend the demo code to send a partial PATCH request with the help of our package: + + ```c# + var updatePersonRequest = new UpdatePersonRequestDocument + { + Data = new DataInUpdatePersonRequest + { + Id = "1", + // Using TrackChangesFor to send "firstName: null" instead of omitting it. + Attributes = new TrackChangesFor(_apiClient) + { + Initializer = + { + FirstName = null, + LastName = "Doe" + } + }.Initializer + } + }; + + await ApiResponse.TranslateAsync(async () => + await _apiClient.PatchPersonAsync(updatePersonRequest.Data.Id, updatePersonRequest)); + + // The sent request looks like this: + // { + // "data": { + // "type": "people", + // "id": "1", + // "attributes": { + // "firstName": null, + // "lastName": "Doe" + // } + // } + // } + ``` + +> [!TIP] +> The [example project](https://github.com/json-api-dotnet/JsonApiDotNetCore/tree/master/src/Examples/OpenApiNSwagClientExample) contains an enhanced version +> that uses `IHttpClientFactory` for [scalability](https://learn.microsoft.com/dotnet/core/extensions/httpclient-factory) and +> [resiliency](https://learn.microsoft.com/aspnet/core/fundamentals/http-requests#use-polly-based-handlers) and logs the HTTP requests and responses. +> Additionally, the example shows how to write the swagger.json file to disk when building the server, which is imported from the client project. +> This keeps the server and client automatically in sync, which is handy when both are in the same solution. + +### Other IDEs + +The following section shows what to add to your client project file directly: + +```xml + + + + + + + + + http://localhost:14140/swagger/v1/swagger.json + ExampleApiClient + %(ClassName).cs + + +``` + +From here, continue from step 3 in the list of steps for Visual Studio. + +# [Kiota](#tab/kiota) + +To generate your C# client, first add the Kiota tool to your solution: + +``` +dotnet tool install microsoft.openapi.kiota +``` + +After adding the `JsonApiDotNetCore.OpenApi.Client.Kiota` package to your project, add a `KiotaReference` element +to your project file to import your OpenAPI file. For example: + +```xml + + + + $(MSBuildProjectName).GeneratedCode + ExampleApiClient + ./GeneratedCode + $(JsonApiExtraArguments) + + + +``` + +> [!NOTE] +> The `ExtraArguments` parameter is required for compatibility with JSON:API. + +Next, build your project. It runs the kiota command-line tool, which generates files in the `GeneratedCode` subdirectory. + +> [!CAUTION] +> If you're not using ``, at least make sure you're passing the `--backing-store` switch to the command-line tool, +> which is needed for JSON:API partial POST/PATCH requests to work correctly. + +Kiota is pretty young and therefore still rough around the edges. At the time of writing, there are various bugs, for which we have workarounds +in place. For a full example, see the [example project](https://github.com/json-api-dotnet/JsonApiDotNetCore/tree/master/src/Examples/OpenApiKiotaClientExample). + +--- + +## Configuration + +Various switches enable you to tweak the client generation to your needs. See the section below for an overview. + +# [NSwag](#tab/nswag) + +The `OpenApiReference` element can be customized using various [NSwag-specific MSBuild properties](https://github.com/RicoSuter/NSwag/blob/7d6df3af95081f3f0ed6dee04be8d27faa86f91a/src/NSwag.ApiDescription.Client/NSwag.ApiDescription.Client.props). +See [the source code](https://github.com/RicoSuter/NSwag/blob/master/src/NSwag.Commands/Commands/CodeGeneration/OpenApiToCSharpClientCommand.cs) for their meaning. +The `JsonApiDotNetCore.OpenApi.Client.NSwag` package sets various of these for optimal JSON:API support. + +> [!NOTE] +> Earlier versions of NSwag required the use of `` to specify command-line switches directly. +> This is no longer recommended and may conflict with the new MSBuild properties. + +For example, the following section puts the generated code in a namespace, makes the client class internal and generates an interface (handy when writing tests): + +```xml + + ExampleProject.GeneratedCode + internal + true + +``` + +# [Kiota](#tab/kiota) + +The available command-line switches for Kiota are described [here](https://learn.microsoft.com/openapi/kiota/using#client-generation). + +At the time of writing, Kiota provides [no official integration](https://github.com/microsoft/kiota/issues/3005) with MSBuild. +Our [example project](https://github.com/json-api-dotnet/JsonApiDotNetCore/tree/master/src/Examples/OpenApiKiotaClientExample) takes a stab at it, +which seems to work. If you're an MSBuild expert, please help out! + +```xml + + + + + + + + + + + + + + + +``` + +--- + +## Headers and caching + +The use of HTTP headers varies per client generator. To use [ETags for caching](~/usage/caching.md), see the notes below. + +# [NSwag](#tab/nswag) + +To gain access to HTTP response headers, add the following in a `PropertyGroup` or directly in the `OpenApiReference`: + +``` +true +``` + +This enables the following code, which is explained below: + +```c# +var getResponse = await ApiResponse.TranslateAsync(() => apiClient.GetPersonCollectionAsync()); +string eTag = getResponse.Headers["ETag"].Single(); +Console.WriteLine($"Retrieved {getResponse.Result?.Data.Count ?? 0} people."); + +// wait some time... + +getResponse = await ApiResponse.TranslateAsync(() => apiClient.GetPersonCollectionAsync(if_None_Match: eTag)); + +if (getResponse is { StatusCode: (int)HttpStatusCode.NotModified, Result: null }) +{ + Console.WriteLine("The HTTP response hasn't changed, so no response body was returned."); +} +``` + +The response of the first API call contains both data and an ETag header, which is a fingerprint of the response. +That ETag gets passed to the second API call. This enables the server to detect if something changed, which optimizes +network usage: no data is sent back, unless is has changed. +If you only want to ask whether data has changed without fetching it, use a HEAD request instead. + +# [Kiota](#tab/kiota) + +Use `HeadersInspectionHandlerOption` to gain access to HTTP response headers. For example: + +```c# +var headerInspector = new HeadersInspectionHandlerOption +{ + InspectResponseHeaders = true +}; + +var responseDocument = await apiClient.Api.People.GetAsync(configuration => configuration.Options.Add(headerInspector)); + +string eTag = headerInspector.ResponseHeaders["ETag"].Single(); +``` + +Due to a [bug in Kiota](https://github.com/microsoft/kiota/issues/4190), a try/catch block is needed additionally to make this work. + +For a full example, see the [example project](https://github.com/json-api-dotnet/JsonApiDotNetCore/tree/master/src/Examples/OpenApiKiotaClientExample). + +--- + +## Atomic operations + +# [NSwag](#tab/nswag) + +[Atomic operations](~/usage/writing/bulk-batch-operations.md) are fully supported. +The [example project](https://github.com/json-api-dotnet/JsonApiDotNetCore/tree/master/src/Examples/OpenApiNSwagClientExample) +demonstrates how to use them. It uses local IDs to: +- Create a new tag +- Create a new person +- Update the person to clear an attribute (using `TrackChangesFor`) +- Create a new todo-item, tagged with the new tag, and owned by the new person +- Assign the todo-item to the created person + +# [Kiota](#tab/kiota) + +[Atomic operations](~/usage/writing/bulk-batch-operations.md) are fully supported. +See the [example project](https://github.com/json-api-dotnet/JsonApiDotNetCore/tree/master/src/Examples/OpenApiKiotaClientExample) +demonstrates how to use them. It uses local IDs to: +- Create a new tag +- Create a new person +- Update the person to clear an attribute (using built-in backing-store) +- Create a new todo-item, tagged with the new tag, and owned by the new person +- Assign the todo-item to the created person + +--- + +## Known limitations + +# [NSwag](#tab/nswag) + +| Limitation | Workaround | Links | +| --- | --- | --- | +| Partial POST/PATCH sends incorrect request | Use `TrackChangesFor` from `JsonApiDotNetCore.OpenApi.Client.NSwag` package | | +| Exception thrown on successful HTTP status | Use `TranslateAsync` from `JsonApiDotNetCore.OpenApi.Client.NSwag` package | https://github.com/RicoSuter/NSwag/issues/2499 | +| No `Accept` header sent when only error responses define `Content-Type` | `JsonApiDotNetCore.OpenApi.Swashbuckle` package contains workaround | | +| Schema type not always inferred with `allOf` | `JsonApiDotNetCore.OpenApi.Swashbuckle` package contains workaround | | +| Generated code for JSON:API extensions does not compile | `JsonApiDotNetCore.OpenApi.Swashbuckle` package contains workaround | | +| A project can't contain both JSON:API clients and regular OpenAPI clients | Use separate projects | | + +# [Kiota](#tab/kiota) + +| Limitation | Workaround | Links | +| --- | --- | --- | +| Properties are always nullable | - | https://github.com/microsoft/kiota/issues/3911 | +| JSON:API query strings are inaccessible | Use `SetQueryStringHttpMessageHandler.CreateScope` from `JsonApiDotNetCore.OpenApi.Client.Kiota` package | https://github.com/microsoft/kiota/issues/3800 | +| Properties set to `null` are sent twice | - | https://github.com/microsoft/kiota-dotnet/issues/535 | +| HTTP 304 (Not Modified) is not properly recognized | Catch `ApiException` and inspect the response status code | https://github.com/microsoft/kiota/issues/4190, https://github.com/microsoft/kiota-dotnet/issues/531 | +| Generator warns about unsupported formats | Use `JsonApiDotNetCore.OpenApi.Client.Kiota` package | https://github.com/microsoft/kiota/issues/4227 | +| `Stream` response for HEAD request | - | https://github.com/microsoft/kiota/issues/4245 | +| Unhelpful exception messages | - | https://github.com/microsoft/kiota/issues/4349 | +| Discriminator properties aren't being set automatically | - | https://github.com/microsoft/kiota/issues/4618 | +| Discriminator mappings must be repeated in every derived type used in responses | `JsonApiDotNetCore.OpenApi.Swashbuckle` package contains workaround | https://github.com/microsoft/kiota/issues/2432 | +| `x-abstract` in `openapi.json` is ignored | - | | +| No MSBuild / IDE support | Use `KiotaReference` from `JsonApiDotNetCore.OpenApi.Client.Kiota` package | https://github.com/microsoft/kiota/issues/3005 | +| Incorrect nullability in API methods | Use `KiotaReference` from `JsonApiDotNetCore.OpenApi.Client.Kiota` package | https://github.com/microsoft/kiota/issues/3944 | +| Generated code for JSON:API extensions does not compile | `JsonApiDotNetCore.OpenApi.Swashbuckle` package contains workaround | | +| Properties are always sent in alphabetic order | - | https://github.com/microsoft/kiota/issues/4680 | + +--- diff --git a/docs/usage/openapi-documentation.md b/docs/usage/openapi-documentation.md new file mode 100644 index 0000000000..6737bd6404 --- /dev/null +++ b/docs/usage/openapi-documentation.md @@ -0,0 +1,48 @@ +> [!WARNING] +> OpenAPI support for JSON:API is currently experimental. The API and the structure of the OpenAPI document may change in future versions. + +# OpenAPI documentation + +After [enabling OpenAPI](~/usage/openapi.md), you can expose a documentation website with SwaggerUI, Redoc and/or Scalar. + +## SwaggerUI + +[SwaggerUI](https://swagger.io/tools/swagger-ui/) enables to visualize and interact with the JSON:API endpoints through a web page. +While it conveniently provides the ability to execute requests, it doesn't show properties of derived types when component schema inheritance is used. + +SwaggerUI can be enabled by installing the `Swashbuckle.AspNetCore.SwaggerUI` NuGet package and adding the following to your `Program.cs` file: + +```c# +app.UseSwaggerUI(); +``` + +Then run your app and open `/swagger` in your browser. + +## Redoc + +[Redoc](https://github.com/Redocly/redoc) is another popular tool that generates a documentation website from an OpenAPI document. +It lists the endpoints and their schemas, but doesn't provide the ability to execute requests. +However, this tool most accurately reflects properties when component schema inheritance is used; choosing a different "type" from the +dropdown box dynamically adapts the list of schema properties. + +The `Swashbuckle.AspNetCore.ReDoc` NuGet package provides integration with Swashbuckle. +After installing the package, add the following to your `Program.cs` file: + +```c# +app.UseReDoc(); +``` + +Next, run your app and navigate to `/api-docs` to view the documentation. + +## Scalar + +[Scalar](https://scalar.com/) is a modern documentation website generator, which includes the ability to execute requests. +It shows component schemas in a low-level way (not collapsing `allOf` nodes), but does a poor job in handling component schema inheritance. + +After installing the `Scalar.AspNetCore` NuGet package, add the following to your `Program.cs` to make it use the OpenAPI document produced by Swashbuckle: + +```c# +app.MapScalarApiReference(options => options.OpenApiRoutePattern = "/swagger/{documentName}/swagger.json"); +``` + +Then run your app and navigate to `/scalar/v1` to view the documentation. diff --git a/docs/usage/openapi.md b/docs/usage/openapi.md new file mode 100644 index 0000000000..e49f120a14 --- /dev/null +++ b/docs/usage/openapi.md @@ -0,0 +1,87 @@ +> [!WARNING] +> OpenAPI support for JSON:API is currently experimental. The API and the structure of the OpenAPI document may change in future versions. + +# OpenAPI + +Exposing an [OpenAPI document](https://swagger.io/specification/) for your JSON:API endpoints enables to provide a +[documentation website](https://swagger.io/tools/swagger-ui/) and to generate typed +[client libraries](https://openapi-generator.tech/docs/generators/) in various languages. + +The [JsonApiDotNetCore.OpenApi.Swashbuckle](https://github.com/json-api-dotnet/JsonApiDotNetCore/pkgs/nuget/JsonApiDotNetCore.OpenApi.Swashbuckle) NuGet package +provides OpenAPI support for JSON:API by integrating with [Swashbuckle](https://github.com/domaindrivendev/Swashbuckle.AspNetCore). + +## Getting started + +1. Install the `JsonApiDotNetCore.OpenApi.Swashbuckle` NuGet package: + + ``` + dotnet add package JsonApiDotNetCore.OpenApi.Swashbuckle + ``` + + > [!NOTE] + > Because this package is still experimental, it's not yet available on NuGet. + > Use the steps [here](https://github.com/json-api-dotnet/JsonApiDotNetCore?tab=readme-ov-file#trying-out-the-latest-build) to install. + +2. Add the JSON:API support to your `Program.cs` file. + + ```c# + builder.Services.AddJsonApi(); + + // Configure Swashbuckle for JSON:API. + builder.Services.AddOpenApiForJsonApi(); + + var app = builder.Build(); + + app.UseRouting(); + app.UseJsonApi(); + + // Add the Swashbuckle middleware. + app.UseSwagger(); + ``` + +By default, the OpenAPI document will be available at `http://localhost:/swagger/v1/swagger.json`. + +### Customizing the Route Template + +Because Swashbuckle doesn't properly implement the ASP.NET Options pattern, you must *not* use its +[documented way](https://github.com/domaindrivendev/Swashbuckle.AspNetCore?tab=readme-ov-file#change-the-path-for-swagger-json-endpoints) +to change the route template: + +```c# +// DO NOT USE THIS! INCOMPATIBLE WITH JSON:API! +app.UseSwagger(options => options.RouteTemplate = "api-docs/{documentName}/swagger.yaml"); +``` + +Instead, always call `UseSwagger()` *without parameters*. To change the route template, use the code below: + +```c# +builder.Services.Configure(options => options.RouteTemplate = "/api-docs/{documentName}/swagger.yaml"); +``` + +If you want to inject dependencies to set the route template, use: + +```c# +builder.Services.AddOptions().Configure((options, serviceProvider) => +{ + var webHostEnvironment = serviceProvider.GetRequiredService(); + string appName = webHostEnvironment.ApplicationName; + options.RouteTemplate = $"/api-docs/{{documentName}}/{appName}-swagger.yaml"; +}); +``` + +## Triple-slash comments + +Documentation for JSON:API endpoints is provided out of the box, which shows in SwaggerUI and through IDE IntelliSense in auto-generated clients. +To also get documentation for your resource classes and their properties, add the following to your project file. +The `NoWarn` line is optional, which suppresses build warnings for undocumented types and members. + +```xml + + True + $(NoWarn);1591 + +``` + +You can combine this with the documentation that Swagger itself supports, by enabling it as described +[here](https://github.com/domaindrivendev/Swashbuckle.AspNetCore#include-descriptions-from-xml-comments). +This adds documentation for additional types, such as triple-slash comments on enums used in your resource models. diff --git a/docs/usage/options.md b/docs/usage/options.md index 7607ac8a9e..7e89ff0090 100644 --- a/docs/usage/options.md +++ b/docs/usage/options.md @@ -122,7 +122,7 @@ Because we copy resource properties into an intermediate object before serializa ## ModelState Validation -[ASP.NET ModelState validation](https://docs.microsoft.com/en-us/aspnet/core/mvc/models/validation) can be used to validate incoming request bodies when creating and updating resources. Since v5.0, this is enabled by default. +[ASP.NET ModelState validation](https://learn.microsoft.com/aspnet/web-api/overview/formats-and-model-binding/model-validation-in-aspnet-web-api) can be used to validate incoming request bodies when creating and updating resources. Since v5.0, this is enabled by default. When `ValidateModelState` is set to `false`, no model validation is performed. How nullability affects ModelState validation is described [here](~/usage/resources/nullability.md). diff --git a/docs/usage/reading/filtering.md b/docs/usage/reading/filtering.md index 8a568078a0..05c3066644 100644 --- a/docs/usage/reading/filtering.md +++ b/docs/usage/reading/filtering.md @@ -60,7 +60,7 @@ The next request returns all customers that have orders -or- whose last name is GET /customers?filter=has(orders)&filter=equals(lastName,'Smith') HTTP/1.1 ``` -Aside from filtering on the resource being requested (which would be blogs in /blogs and articles in /blogs/1/articles), +Aside from filtering on the resource being requested (which would be blogs in /blogs and articles in /blogs/1/articles), filtering on to-many relationships can be done using bracket notation: ```http diff --git a/docs/usage/resource-graph.md b/docs/usage/resource-graph.md index 18a13da907..046daaf7f5 100644 --- a/docs/usage/resource-graph.md +++ b/docs/usage/resource-graph.md @@ -14,7 +14,7 @@ There are three ways the resource graph can be created: 2. Specifying an entire DbContext 3. Manually specifying each resource -It is also possible to combine the three of them at once. Be aware that some configuration might overlap, +It is also possible to combine the three of them at once. Be aware that some configuration might overlap, for example one could manually add a resource to the graph which is also auto-discovered. In such a scenario, the configuration is prioritized by the list above in descending order. diff --git a/docs/usage/resources/nullability.md b/docs/usage/resources/nullability.md index 24b15572fc..875b133a01 100644 --- a/docs/usage/resources/nullability.md +++ b/docs/usage/resources/nullability.md @@ -24,7 +24,7 @@ This makes Entity Framework Core generate non-nullable columns. And model errors # Reference types -When the [nullable reference types](https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references) (NRT) compiler feature is enabled, it affects both ASP.NET ModelState validation and Entity Framework Core. +When the [nullable reference types](https://learn.microsoft.com/dotnet/csharp/nullable-references) (NRT) compiler feature is enabled, it affects both ASP.NET ModelState validation and Entity Framework Core. ## NRT turned off @@ -60,7 +60,7 @@ public sealed class Label : Identifiable When NRT is turned on, use nullability annotations (?) on attributes and relationships. This makes Entity Framework Core generate non-nullable columns. And model errors are returned when non-nullable fields are omitted. -The [Entity Framework Core guide on NRT](https://docs.microsoft.com/en-us/ef/core/miscellaneous/nullable-reference-types) recommends to use constructor binding to initialize non-nullable properties, but JsonApiDotNetCore does not support that. For required navigation properties, it suggests to use a non-nullable property with a nullable backing field. JsonApiDotNetCore does not support that either. In both cases, just use the null-forgiving operator (!). +The [Entity Framework Core guide on NRT](https://learn.microsoft.com/ef/core/miscellaneous/nullable-reference-types) recommends to use constructor binding to initialize non-nullable properties, but JsonApiDotNetCore does not support that. For required navigation properties, it suggests to use a non-nullable property with a nullable backing field. JsonApiDotNetCore does not support that either. In both cases, just use the null-forgiving operator (!). When ModelState validation is turned on, to-many relationships must be assigned an empty collection. Otherwise an error is returned when they don't occur in the request body. diff --git a/docs/usage/resources/relationships.md b/docs/usage/resources/relationships.md index 689b3aa4d2..f318b2ddcd 100644 --- a/docs/usage/resources/relationships.md +++ b/docs/usage/resources/relationships.md @@ -1,7 +1,7 @@ # Relationships A relationship is a named link between two resource types, including a direction. -They are similar to [navigation properties in Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/modeling/relationships). +They are similar to [navigation properties in Entity Framework Core](https://learn.microsoft.com/ef/core/modeling/relationships). Relationships come in two flavors: to-one and to-many. The left side of a relationship is where the relationship is declared, the right side is the resource type it points to. @@ -113,7 +113,7 @@ For optional one-to-one relationships, Entity Framework Core uses `DeleteBehavio This means that Entity Framework Core tries to handle the cascading effects (by sending multiple SQL statements), instead of leaving it up to the database. Of course that's only going to work when all the related resources are loaded in the change tracker upfront, which is expensive because it requires fetching more data than necessary. -The reason for this odd default is poor support in SQL Server, as explained [here](https://stackoverflow.com/questions/54326165/ef-core-why-clientsetnull-is-default-ondelete-behavior-for-optional-relations) and [here](https://learn.microsoft.com/en-us/ef/core/saving/cascade-delete#database-cascade-limitations). +The reason for this odd default is poor support in SQL Server, as explained [here](https://stackoverflow.com/questions/54326165/ef-core-why-clientsetnull-is-default-ondelete-behavior-for-optional-relations) and [here](https://learn.microsoft.com/ef/core/saving/cascade-delete#database-cascade-limitations). **Our [testing](https://github.com/json-api-dotnet/JsonApiDotNetCore/pull/1205) shows that these limitations don't exist when using PostgreSQL. Therefore the general advice is to map the delete behavior of optional one-to-one relationships explicitly with `.OnDelete(DeleteBehavior.SetNull)`. This is simpler and more efficient.** @@ -261,8 +261,8 @@ public class TodoItem : Identifiable _since v5.1_ -Default JSON:API relationship capabilities are specified in -@JsonApiDotNetCore.Configuration.JsonApiOptions#JsonApiDotNetCore_Configuration_JsonApiOptions_DefaultHasOneCapabilities and +Default JSON:API relationship capabilities are specified in +@JsonApiDotNetCore.Configuration.JsonApiOptions#JsonApiDotNetCore_Configuration_JsonApiOptions_DefaultHasOneCapabilities and @JsonApiDotNetCore.Configuration.JsonApiOptions#JsonApiDotNetCore_Configuration_JsonApiOptions_DefaultHasManyCapabilities: ```c# diff --git a/docs/usage/routing.md b/docs/usage/routing.md index e3e021ec23..cb1197e86a 100644 --- a/docs/usage/routing.md +++ b/docs/usage/routing.md @@ -86,7 +86,7 @@ public class OrderLineController : JsonApiController ## Advanced usage: custom routing convention -It is possible to replace the built-in routing convention with a [custom routing convention](https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/application-model?view=aspnetcore-3.1#sample-custom-routing-convention) by registering an implementation of `IJsonApiRoutingConvention`. +It is possible to replace the built-in routing convention with a [custom routing convention](https://learn.microsoft.com/aspnet/core/mvc/controllers/application-model#custom-routing-convention) by registering an implementation of `IJsonApiRoutingConvention`. ```c# // Program.cs diff --git a/docs/usage/toc.md b/docs/usage/toc.md index 61d3da8de0..bdeb0e4958 100644 --- a/docs/usage/toc.md +++ b/docs/usage/toc.md @@ -25,6 +25,10 @@ # [Caching](caching.md) # [Common Pitfalls](common-pitfalls.md) +# [OpenAPI](openapi.md) +## [Documentation](openapi-documentation.md) +## [Clients](openapi-client.md) + # Extensibility ## [Layer Overview](extensibility/layer-overview.md) ## [Resource Definitions](extensibility/resource-definitions.md) diff --git a/docs/usage/writing/bulk-batch-operations.md b/docs/usage/writing/bulk-batch-operations.md index 5756755b51..c8ba2bf48e 100644 --- a/docs/usage/writing/bulk-batch-operations.md +++ b/docs/usage/writing/bulk-batch-operations.md @@ -28,7 +28,7 @@ public sealed class OperationsController : JsonApiOperationsController } ``` -> [!IMPORTANT] +> [!IMPORTANT] > Since v5.6.0, the set of exposed operations is based on > [`GenerateControllerEndpoints` usage](~/usage/extensibility/controllers.md#resource-access-control). > Earlier versions always exposed all operations for all resource types. diff --git a/nuget.config b/nuget.config new file mode 100644 index 0000000000..16164967c6 --- /dev/null +++ b/nuget.config @@ -0,0 +1,7 @@ + + + + + + + diff --git a/package-versions.props b/package-versions.props index 9ba0b34bbb..8b528ff324 100644 --- a/package-versions.props +++ b/package-versions.props @@ -4,39 +4,49 @@ 4.1.0 0.4.1 2.14.1 + 8.0.0 + 13.0.3 - 0.13.* - 35.5.* - 4.10.* + 0.14.* + 1.0.* + 35.6.* + 4.13.* 6.0.* 2.1.* - 6.12.* - 2.3.* + 7.2.* + 2.4.* 2.0.* - 8.0.* - 17.10.* - 2.8.* + 1.* + 9.0.* + 9.0.* + 14.3.* + 13.0.* + 2.1.* + 8.*-* + 9.0.* + 17.13.* + 2.9.* + 2.8.* - + - 8.0.0 + N/A - 8.0.* - 8.0.* - $(AspNetCoreVersion) + 9.0.* + 9.0.* + 9.0.0-* - + - 6.0.0 + 8.0.0 - 6.0.* - 2.1.* - 7.0.* - 7.0.* + 8.0.* + 8.0.* + $(EntityFrameworkCoreVersion) diff --git a/src/Examples/DapperExample/AtomicOperations/AmbientTransaction.cs b/src/Examples/DapperExample/AtomicOperations/AmbientTransaction.cs index c442861bc4..11d052da66 100644 --- a/src/Examples/DapperExample/AtomicOperations/AmbientTransaction.cs +++ b/src/Examples/DapperExample/AtomicOperations/AmbientTransaction.cs @@ -1,5 +1,4 @@ using System.Data.Common; -using JsonApiDotNetCore; using JsonApiDotNetCore.AtomicOperations; namespace DapperExample.AtomicOperations; @@ -18,8 +17,8 @@ internal sealed class AmbientTransaction : IOperationsTransaction public AmbientTransaction(AmbientTransactionFactory owner, DbTransaction current, Guid transactionId) { - ArgumentGuard.NotNull(owner); - ArgumentGuard.NotNull(current); + ArgumentNullException.ThrowIfNull(owner); + ArgumentNullException.ThrowIfNull(current); _owner = owner; Current = current; diff --git a/src/Examples/DapperExample/AtomicOperations/AmbientTransactionFactory.cs b/src/Examples/DapperExample/AtomicOperations/AmbientTransactionFactory.cs index d10959b79a..82790819fe 100644 --- a/src/Examples/DapperExample/AtomicOperations/AmbientTransactionFactory.cs +++ b/src/Examples/DapperExample/AtomicOperations/AmbientTransactionFactory.cs @@ -1,6 +1,5 @@ using System.Data.Common; using DapperExample.TranslationToSql.DataModel; -using JsonApiDotNetCore; using JsonApiDotNetCore.AtomicOperations; using JsonApiDotNetCore.Configuration; @@ -18,8 +17,8 @@ public sealed class AmbientTransactionFactory : IOperationsTransactionFactory public AmbientTransactionFactory(IJsonApiOptions options, IDataModelService dataModelService) { - ArgumentGuard.NotNull(options); - ArgumentGuard.NotNull(dataModelService); + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(dataModelService); _options = options; _dataModelService = dataModelService; @@ -64,7 +63,7 @@ async Task IOperationsTransactionFactory.BeginTransactio internal void Detach(AmbientTransaction ambientTransaction) { - ArgumentGuard.NotNull(ambientTransaction); + ArgumentNullException.ThrowIfNull(ambientTransaction); if (AmbientTransaction != null && AmbientTransaction == ambientTransaction) { diff --git a/src/Examples/DapperExample/Controllers/OperationsController.cs b/src/Examples/DapperExample/Controllers/OperationsController.cs index 2b9daf492f..ed15c6e9a2 100644 --- a/src/Examples/DapperExample/Controllers/OperationsController.cs +++ b/src/Examples/DapperExample/Controllers/OperationsController.cs @@ -8,5 +8,5 @@ namespace DapperExample.Controllers; public sealed class OperationsController( IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, IOperationsProcessor processor, IJsonApiRequest request, - ITargetedFields targetedFields, IAtomicOperationFilter operationFilter) : JsonApiOperationsController(options, resourceGraph, loggerFactory, processor, - request, targetedFields, operationFilter); + ITargetedFields targetedFields, IAtomicOperationFilter operationFilter) + : JsonApiOperationsController(options, resourceGraph, loggerFactory, processor, request, targetedFields, operationFilter); diff --git a/src/Examples/DapperExample/DapperExample.csproj b/src/Examples/DapperExample/DapperExample.csproj index f49c3e4b40..ed7bd358eb 100644 --- a/src/Examples/DapperExample/DapperExample.csproj +++ b/src/Examples/DapperExample/DapperExample.csproj @@ -1,6 +1,6 @@ - net8.0;net6.0 + net9.0;net8.0 @@ -16,6 +16,6 @@ - + diff --git a/src/Examples/DapperExample/Data/AppDbContext.cs b/src/Examples/DapperExample/Data/AppDbContext.cs index ee18bab08e..31f09b277c 100644 --- a/src/Examples/DapperExample/Data/AppDbContext.cs +++ b/src/Examples/DapperExample/Data/AppDbContext.cs @@ -1,6 +1,5 @@ using DapperExample.Models; using JetBrains.Annotations; -using JsonApiDotNetCore; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata; @@ -23,7 +22,7 @@ public sealed class AppDbContext : DbContext public AppDbContext(DbContextOptions options, IConfiguration configuration) : base(options) { - ArgumentGuard.NotNull(configuration); + ArgumentNullException.ThrowIfNull(configuration); _configuration = configuration; } diff --git a/src/Examples/DapperExample/Definitions/TodoItemDefinition.cs b/src/Examples/DapperExample/Definitions/TodoItemDefinition.cs index dc7c1802c8..f20268fb7d 100644 --- a/src/Examples/DapperExample/Definitions/TodoItemDefinition.cs +++ b/src/Examples/DapperExample/Definitions/TodoItemDefinition.cs @@ -1,7 +1,6 @@ using System.ComponentModel; using DapperExample.Models; using JetBrains.Annotations; -using JsonApiDotNetCore; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Middleware; using JsonApiDotNetCore.Queries.Expressions; @@ -12,14 +11,14 @@ namespace DapperExample.Definitions; [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] public sealed class TodoItemDefinition : JsonApiResourceDefinition { - private readonly IClock _clock; + private readonly TimeProvider _timeProvider; - public TodoItemDefinition(IResourceGraph resourceGraph, IClock clock) + public TodoItemDefinition(IResourceGraph resourceGraph, TimeProvider timeProvider) : base(resourceGraph) { - ArgumentGuard.NotNull(clock); + ArgumentNullException.ThrowIfNull(timeProvider); - _clock = clock; + _timeProvider = timeProvider; } public override SortExpression OnApplySort(SortExpression? existingSort) @@ -39,11 +38,11 @@ public override Task OnWritingAsync(TodoItem resource, WriteOperationKind writeO { if (writeOperation == WriteOperationKind.CreateResource) { - resource.CreatedAt = _clock.UtcNow; + resource.CreatedAt = _timeProvider.GetUtcNow(); } else if (writeOperation == WriteOperationKind.UpdateResource) { - resource.LastModifiedAt = _clock.UtcNow; + resource.LastModifiedAt = _timeProvider.GetUtcNow(); } return Task.CompletedTask; diff --git a/src/Examples/DapperExample/FromEntitiesNavigationResolver.cs b/src/Examples/DapperExample/FromEntitiesNavigationResolver.cs index 8ab88473c1..4ae5f05dcc 100644 --- a/src/Examples/DapperExample/FromEntitiesNavigationResolver.cs +++ b/src/Examples/DapperExample/FromEntitiesNavigationResolver.cs @@ -1,6 +1,5 @@ using DapperExample.Data; using DapperExample.TranslationToSql.DataModel; -using JsonApiDotNetCore; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Repositories; using Microsoft.EntityFrameworkCore; @@ -18,9 +17,9 @@ internal sealed class FromEntitiesNavigationResolver : IInverseNavigationResolve public FromEntitiesNavigationResolver(IResourceGraph resourceGraph, FromEntitiesDataModelService dataModelService, AppDbContext appDbContext) { - ArgumentGuard.NotNull(resourceGraph); - ArgumentGuard.NotNull(dataModelService); - ArgumentGuard.NotNull(appDbContext); + ArgumentNullException.ThrowIfNull(resourceGraph); + ArgumentNullException.ThrowIfNull(dataModelService); + ArgumentNullException.ThrowIfNull(appDbContext); _defaultResolver = new InverseNavigationResolver(resourceGraph, new[] { diff --git a/src/Examples/DapperExample/IClock.cs b/src/Examples/DapperExample/IClock.cs deleted file mode 100644 index 0319c42480..0000000000 --- a/src/Examples/DapperExample/IClock.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace DapperExample; - -public interface IClock -{ - DateTimeOffset UtcNow { get; } -} diff --git a/src/Examples/DapperExample/Program.cs b/src/Examples/DapperExample/Program.cs index 00ab54ca97..6e84497d02 100644 --- a/src/Examples/DapperExample/Program.cs +++ b/src/Examples/DapperExample/Program.cs @@ -11,13 +11,12 @@ using JsonApiDotNetCore.Repositories; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; -using Microsoft.Extensions.DependencyInjection.Extensions; WebApplicationBuilder builder = WebApplication.CreateBuilder(args); // Add services to the container. -builder.Services.TryAddSingleton(); +builder.Services.AddSingleton(); DatabaseProvider databaseProvider = GetDatabaseProvider(builder.Configuration); string? connectionString = builder.Configuration.GetConnectionString($"DapperExample{databaseProvider}"); @@ -31,8 +30,13 @@ } case DatabaseProvider.MySql: { - builder.Services.AddMySql(connectionString, ServerVersion.AutoDetect(connectionString), - optionsAction: options => SetDbContextDebugOptions(options)); +#if NET8_0 + ServerVersion serverVersion = ServerVersion.AutoDetect(connectionString); +#else + ServerVersion serverVersion = await ServerVersion.AutoDetectAsync(connectionString); +#endif + + builder.Services.AddMySql(connectionString, serverVersion, optionsAction: options => SetDbContextDebugOptions(options)); break; } @@ -86,7 +90,7 @@ await CreateDatabaseAsync(app.Services); -app.Run(); +await app.RunAsync(); static DatabaseProvider GetDatabaseProvider(IConfiguration configuration) { diff --git a/src/Examples/DapperExample/Repositories/DapperFacade.cs b/src/Examples/DapperExample/Repositories/DapperFacade.cs index 4d30e430c7..e7190ec0de 100644 --- a/src/Examples/DapperExample/Repositories/DapperFacade.cs +++ b/src/Examples/DapperExample/Repositories/DapperFacade.cs @@ -17,14 +17,14 @@ internal sealed class DapperFacade public DapperFacade(IDataModelService dataModelService) { - ArgumentGuard.NotNull(dataModelService); + ArgumentNullException.ThrowIfNull(dataModelService); _dataModelService = dataModelService; } public CommandDefinition GetSqlCommand(SqlTreeNode node, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(node); + ArgumentNullException.ThrowIfNull(node); var queryBuilder = new SqlQueryBuilder(_dataModelService.DatabaseProvider); string statement = queryBuilder.GetCommand(node); @@ -36,7 +36,7 @@ public CommandDefinition GetSqlCommand(SqlTreeNode node, CancellationToken cance public IReadOnlyCollection BuildSqlCommandsForOneToOneRelationshipsChangedToNotNull(ResourceChangeDetector changeDetector, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(changeDetector); + ArgumentNullException.ThrowIfNull(changeDetector); List sqlCommands = []; @@ -73,13 +73,13 @@ public IReadOnlyCollection BuildSqlCommandsForOneToOneRelatio } } - return sqlCommands; + return sqlCommands.AsReadOnly(); } public IReadOnlyCollection BuildSqlCommandsForChangedRelationshipsHavingForeignKeyAtRightSide(ResourceChangeDetector changeDetector, TId leftId, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(changeDetector); + ArgumentNullException.ThrowIfNull(changeDetector); List sqlCommands = []; @@ -107,26 +107,26 @@ public IReadOnlyCollection BuildSqlCommandsForChangedRelation object[] rightIdsToRemove = currentRightIds.Except(newRightIds).ToArray(); object[] rightIdsToAdd = newRightIds.Except(currentRightIds).ToArray(); - if (rightIdsToRemove.Any()) + if (rightIdsToRemove.Length > 0) { CommandDefinition sqlCommand = BuildSqlCommandForRemoveFromToMany(foreignKey, rightIdsToRemove, cancellationToken); sqlCommands.Add(sqlCommand); } - if (rightIdsToAdd.Any()) + if (rightIdsToAdd.Length > 0) { CommandDefinition sqlCommand = BuildSqlCommandForAddToToMany(foreignKey, leftId!, rightIdsToAdd, cancellationToken); sqlCommands.Add(sqlCommand); } } - return sqlCommands; + return sqlCommands.AsReadOnly(); } public CommandDefinition BuildSqlCommandForRemoveFromToMany(RelationshipForeignKey foreignKey, object[] rightResourceIdValues, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(foreignKey); + ArgumentNullException.ThrowIfNull(foreignKey); ArgumentGuard.NotNullNorEmpty(rightResourceIdValues); if (!foreignKey.IsNullable) @@ -149,8 +149,8 @@ public CommandDefinition BuildSqlCommandForRemoveFromToMany(RelationshipForeignK public CommandDefinition BuildSqlCommandForAddToToMany(RelationshipForeignKey foreignKey, object leftId, object[] rightResourceIdValues, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(foreignKey); - ArgumentGuard.NotNull(leftId); + ArgumentNullException.ThrowIfNull(foreignKey); + ArgumentNullException.ThrowIfNull(leftId); ArgumentGuard.NotNullNorEmpty(rightResourceIdValues); var columnsToUpdate = new Dictionary @@ -165,7 +165,7 @@ public CommandDefinition BuildSqlCommandForAddToToMany(RelationshipForeignKey fo public CommandDefinition BuildSqlCommandForCreate(ResourceChangeDetector changeDetector, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(changeDetector); + ArgumentNullException.ThrowIfNull(changeDetector); IReadOnlyDictionary columnsToSet = changeDetector.GetChangedColumnValues(); @@ -176,11 +176,11 @@ public CommandDefinition BuildSqlCommandForCreate(ResourceChangeDetector changeD public CommandDefinition? BuildSqlCommandForUpdate(ResourceChangeDetector changeDetector, TId leftId, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(changeDetector); + ArgumentNullException.ThrowIfNull(changeDetector); IReadOnlyDictionary columnsToUpdate = changeDetector.GetChangedColumnValues(); - if (columnsToUpdate.Any()) + if (columnsToUpdate.Count > 0) { var updateBuilder = new UpdateResourceStatementBuilder(_dataModelService); UpdateNode updateNode = updateBuilder.Build(changeDetector.ResourceType, columnsToUpdate, leftId!); diff --git a/src/Examples/DapperExample/Repositories/DapperRepository.cs b/src/Examples/DapperExample/Repositories/DapperRepository.cs index 0c54b34353..716db19519 100644 --- a/src/Examples/DapperExample/Repositories/DapperRepository.cs +++ b/src/Examples/DapperExample/Repositories/DapperRepository.cs @@ -1,3 +1,4 @@ +using System.Data; using System.Data.Common; using System.Diagnostics.CodeAnalysis; using Dapper; @@ -90,7 +91,7 @@ namespace DapperExample.Repositories; /// /// /// -public sealed class DapperRepository : IResourceRepository, IRepositorySupportsTransaction +public sealed partial class DapperRepository : IResourceRepository, IRepositorySupportsTransaction where TResource : class, IIdentifiable { private readonly ITargetedFields _targetedFields; @@ -102,7 +103,6 @@ public sealed class DapperRepository : IResourceRepository> _logger; - private readonly CollectionConverter _collectionConverter = new(); private readonly ParameterFormatter _parameterFormatter = new(); private readonly DapperFacade _dapperFacade; @@ -114,14 +114,14 @@ public DapperRepository(ITargetedFields targetedFields, IResourceGraph resourceG IResourceDefinitionAccessor resourceDefinitionAccessor, AmbientTransactionFactory transactionFactory, IDataModelService dataModelService, SqlCaptureStore captureStore, ILoggerFactory loggerFactory) { - ArgumentGuard.NotNull(targetedFields); - ArgumentGuard.NotNull(resourceGraph); - ArgumentGuard.NotNull(resourceFactory); - ArgumentGuard.NotNull(resourceDefinitionAccessor); - ArgumentGuard.NotNull(transactionFactory); - ArgumentGuard.NotNull(dataModelService); - ArgumentGuard.NotNull(captureStore); - ArgumentGuard.NotNull(loggerFactory); + ArgumentNullException.ThrowIfNull(targetedFields); + ArgumentNullException.ThrowIfNull(resourceGraph); + ArgumentNullException.ThrowIfNull(resourceFactory); + ArgumentNullException.ThrowIfNull(resourceDefinitionAccessor); + ArgumentNullException.ThrowIfNull(transactionFactory); + ArgumentNullException.ThrowIfNull(dataModelService); + ArgumentNullException.ThrowIfNull(captureStore); + ArgumentNullException.ThrowIfNull(loggerFactory); _targetedFields = targetedFields; _resourceGraph = resourceGraph; @@ -138,7 +138,7 @@ public DapperRepository(ITargetedFields targetedFields, IResourceGraph resourceG /// public async Task> GetAsync(QueryLayer queryLayer, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(queryLayer); + ArgumentNullException.ThrowIfNull(queryLayer); var mapper = new ResultSetMapper(queryLayer.Include); @@ -180,7 +180,7 @@ public async Task CountAsync(FilterExpression? filter, CancellationToken ca /// public Task GetForCreateAsync(Type resourceClrType, [DisallowNull] TId id, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(resourceClrType); + ArgumentNullException.ThrowIfNull(resourceClrType); var resource = (TResource)_resourceFactory.CreateInstance(resourceClrType); resource.Id = id; @@ -191,8 +191,8 @@ public Task GetForCreateAsync(Type resourceClrType, [DisallowNull] TI /// public async Task CreateAsync(TResource resourceFromRequest, TResource resourceForDatabase, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(resourceFromRequest); - ArgumentGuard.NotNull(resourceForDatabase); + ArgumentNullException.ThrowIfNull(resourceFromRequest); + ArgumentNullException.ThrowIfNull(resourceForDatabase); var changeDetector = new ResourceChangeDetector(ResourceType, _dataModelService); @@ -216,7 +216,7 @@ await ExecuteInTransactionAsync(async transaction => if (rowsAffected > 1) { - throw new DataStoreUpdateException(new Exception("Multiple rows found.")); + throw new DataStoreUpdateException(new DataException("Multiple rows found.")); } } @@ -233,7 +233,7 @@ await ExecuteInTransactionAsync(async transaction => if (rowsAffected == 0) { - throw new DataStoreUpdateException(new Exception("Row does not exist.")); + throw new DataStoreUpdateException(new DataException("Row does not exist.")); } } }, cancellationToken); @@ -269,12 +269,12 @@ private async Task ApplyTargetedFieldsAsync(TResource resourceFromRequest, TReso if (relationship is HasManyAttribute hasManyRelationship) { - HashSet rightResourceIds = _collectionConverter.ExtractResources(rightValue).ToHashSet(IdentifiableComparer.Instance); + HashSet rightResourceIds = CollectionConverter.Instance.ExtractResources(rightValue).ToHashSet(IdentifiableComparer.Instance); await _resourceDefinitionAccessor.OnSetToManyRelationshipAsync(leftResource, hasManyRelationship, rightResourceIds, writeOperation, cancellationToken); - return _collectionConverter.CopyToTypedCollection(rightResourceIds, relationship.Property.PropertyType); + return CollectionConverter.Instance.CopyToTypedCollection(rightResourceIds, relationship.Property.PropertyType); } return rightValue; @@ -283,7 +283,7 @@ await _resourceDefinitionAccessor.OnSetToManyRelationshipAsync(leftResource, has /// public async Task GetForUpdateAsync(QueryLayer queryLayer, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(queryLayer); + ArgumentNullException.ThrowIfNull(queryLayer); IReadOnlyCollection resources = await GetAsync(queryLayer, cancellationToken); return resources.FirstOrDefault(); @@ -292,8 +292,8 @@ await _resourceDefinitionAccessor.OnSetToManyRelationshipAsync(leftResource, has /// public async Task UpdateAsync(TResource resourceFromRequest, TResource resourceFromDatabase, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(resourceFromRequest); - ArgumentGuard.NotNull(resourceFromDatabase); + ArgumentNullException.ThrowIfNull(resourceFromRequest); + ArgumentNullException.ThrowIfNull(resourceFromDatabase); var changeDetector = new ResourceChangeDetector(ResourceType, _dataModelService); changeDetector.CaptureCurrentValues(resourceFromDatabase); @@ -313,7 +313,7 @@ public async Task UpdateAsync(TResource resourceFromRequest, TResource resourceF IReadOnlyCollection postSqlCommands = _dapperFacade.BuildSqlCommandsForChangedRelationshipsHavingForeignKeyAtRightSide(changeDetector, resourceFromDatabase.Id, cancellationToken); - if (preSqlCommands.Any() || updateCommand != null || postSqlCommands.Any()) + if (preSqlCommands.Count > 0 || updateCommand != null || postSqlCommands.Count > 0) { await ExecuteInTransactionAsync(async transaction => { @@ -324,7 +324,7 @@ await ExecuteInTransactionAsync(async transaction => if (rowsAffected > 1) { - throw new DataStoreUpdateException(new Exception("Multiple rows found.")); + throw new DataStoreUpdateException(new DataException("Multiple rows found.")); } } @@ -335,7 +335,7 @@ await ExecuteInTransactionAsync(async transaction => if (rowsAffected != 1) { - throw new DataStoreUpdateException(new Exception("Row does not exist or multiple rows found.")); + throw new DataStoreUpdateException(new DataException("Row does not exist or multiple rows found.")); } } @@ -346,7 +346,7 @@ await ExecuteInTransactionAsync(async transaction => if (rowsAffected == 0) { - throw new DataStoreUpdateException(new Exception("Row does not exist.")); + throw new DataStoreUpdateException(new DataException("Row does not exist.")); } } }, cancellationToken); @@ -364,7 +364,7 @@ public async Task DeleteAsync(TResource? resourceFromDatabase, [DisallowNull] TI await _resourceDefinitionAccessor.OnWritingAsync(placeholderResource, WriteOperationKind.DeleteResource, cancellationToken); var deleteBuilder = new DeleteResourceStatementBuilder(_dataModelService); - DeleteNode deleteNode = deleteBuilder.Build(ResourceType, placeholderResource.Id!); + DeleteNode deleteNode = deleteBuilder.Build(ResourceType, placeholderResource.Id); CommandDefinition sqlCommand = _dapperFacade.GetSqlCommand(deleteNode, cancellationToken); await ExecuteInTransactionAsync(async transaction => @@ -374,7 +374,7 @@ await ExecuteInTransactionAsync(async transaction => if (rowsAffected != 1) { - throw new DataStoreUpdateException(new Exception("Row does not exist or multiple rows found.")); + throw new DataStoreUpdateException(new DataException("Row does not exist or multiple rows found.")); } }, cancellationToken); @@ -384,7 +384,7 @@ await ExecuteInTransactionAsync(async transaction => /// public async Task SetRelationshipAsync(TResource leftResource, object? rightValue, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(leftResource); + ArgumentNullException.ThrowIfNull(leftResource); RelationshipAttribute relationship = _targetedFields.Relationships.Single(); @@ -409,7 +409,7 @@ public async Task SetRelationshipAsync(TResource leftResource, object? rightValu IReadOnlyCollection postSqlCommands = _dapperFacade.BuildSqlCommandsForChangedRelationshipsHavingForeignKeyAtRightSide(changeDetector, leftResource.Id, cancellationToken); - if (preSqlCommands.Any() || updateCommand != null || postSqlCommands.Any()) + if (preSqlCommands.Count > 0 || updateCommand != null || postSqlCommands.Count > 0) { await ExecuteInTransactionAsync(async transaction => { @@ -420,7 +420,7 @@ await ExecuteInTransactionAsync(async transaction => if (rowsAffected > 1) { - throw new DataStoreUpdateException(new Exception("Multiple rows found.")); + throw new DataStoreUpdateException(new DataException("Multiple rows found.")); } } @@ -431,7 +431,7 @@ await ExecuteInTransactionAsync(async transaction => if (rowsAffected != 1) { - throw new DataStoreUpdateException(new Exception("Row does not exist or multiple rows found.")); + throw new DataStoreUpdateException(new DataException("Row does not exist or multiple rows found.")); } } @@ -442,7 +442,7 @@ await ExecuteInTransactionAsync(async transaction => if (rowsAffected == 0) { - throw new DataStoreUpdateException(new Exception("Row does not exist.")); + throw new DataStoreUpdateException(new DataException("Row does not exist.")); } } }, cancellationToken); @@ -455,7 +455,7 @@ await ExecuteInTransactionAsync(async transaction => public async Task AddToToManyRelationshipAsync(TResource? leftResource, [DisallowNull] TId leftId, ISet rightResourceIds, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(rightResourceIds); + ArgumentNullException.ThrowIfNull(rightResourceIds); var relationship = (HasManyAttribute)_targetedFields.Relationships.Single(); @@ -463,11 +463,13 @@ public async Task AddToToManyRelationshipAsync(TResource? leftResource, [Disallo leftPlaceholderResource.Id = leftId; await _resourceDefinitionAccessor.OnAddToRelationshipAsync(leftPlaceholderResource, relationship, rightResourceIds, cancellationToken); - relationship.SetValue(leftPlaceholderResource, _collectionConverter.CopyToTypedCollection(rightResourceIds, relationship.Property.PropertyType)); + + relationship.SetValue(leftPlaceholderResource, + CollectionConverter.Instance.CopyToTypedCollection(rightResourceIds, relationship.Property.PropertyType)); await _resourceDefinitionAccessor.OnWritingAsync(leftPlaceholderResource, WriteOperationKind.AddToRelationship, cancellationToken); - if (rightResourceIds.Any()) + if (rightResourceIds.Count > 0) { RelationshipForeignKey foreignKey = _dataModelService.GetForeignKey(relationship); object[] rightResourceIdValues = rightResourceIds.Select(resource => resource.GetTypedId()).ToArray(); @@ -482,7 +484,7 @@ await ExecuteInTransactionAsync(async transaction => if (rowsAffected != rightResourceIdValues.Length) { - throw new DataStoreUpdateException(new Exception("Row does not exist or multiple rows found.")); + throw new DataStoreUpdateException(new DataException("Row does not exist or multiple rows found.")); } }, cancellationToken); @@ -493,17 +495,17 @@ await ExecuteInTransactionAsync(async transaction => /// public async Task RemoveFromToManyRelationshipAsync(TResource leftResource, ISet rightResourceIds, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(leftResource); - ArgumentGuard.NotNull(rightResourceIds); + ArgumentNullException.ThrowIfNull(leftResource); + ArgumentNullException.ThrowIfNull(rightResourceIds); var relationship = (HasManyAttribute)_targetedFields.Relationships.Single(); await _resourceDefinitionAccessor.OnRemoveFromRelationshipAsync(leftResource, relationship, rightResourceIds, cancellationToken); - relationship.SetValue(leftResource, _collectionConverter.CopyToTypedCollection(rightResourceIds, relationship.Property.PropertyType)); + relationship.SetValue(leftResource, CollectionConverter.Instance.CopyToTypedCollection(rightResourceIds, relationship.Property.PropertyType)); await _resourceDefinitionAccessor.OnWritingAsync(leftResource, WriteOperationKind.RemoveFromRelationship, cancellationToken); - if (rightResourceIds.Any()) + if (rightResourceIds.Count > 0) { RelationshipForeignKey foreignKey = _dataModelService.GetForeignKey(relationship); object[] rightResourceIdValues = rightResourceIds.Select(resource => resource.GetTypedId()).ToArray(); @@ -516,7 +518,7 @@ await ExecuteInTransactionAsync(async transaction => if (rowsAffected != rightResourceIdValues.Length) { - throw new DataStoreUpdateException(new Exception("Row does not exist or multiple rows found.")); + throw new DataStoreUpdateException(new DataException("Row does not exist or multiple rows found.")); } }, cancellationToken); @@ -530,19 +532,18 @@ private void LogSqlCommand(CommandDefinition command) _captureStore.Add(command.CommandText, parameters); - string message = GetLogText(command.CommandText, parameters); - _logger.LogInformation(message); - } - - private string GetLogText(string statement, IDictionary? parameters) - { - if (parameters?.Any() == true) + if (_logger.IsEnabled(LogLevel.Information)) { - string parametersText = string.Join(", ", parameters.Select(parameter => _parameterFormatter.Format(parameter.Key, parameter.Value))); - return $"Executing SQL with parameters: {parametersText}{Environment.NewLine}{statement}"; + if (parameters?.Count > 0) + { + string parametersText = string.Join(", ", parameters.Select(parameter => _parameterFormatter.Format(parameter.Key, parameter.Value))); + LogExecuteWithParameters(Environment.NewLine, command.CommandText, parametersText); + } + else + { + LogExecute(Environment.NewLine, command.CommandText); + } } - - return $"Executing SQL: {Environment.NewLine}{statement}"; } private async Task ExecuteQueryAsync(Func> asyncAction, CancellationToken cancellationToken) @@ -580,4 +581,10 @@ private async Task ExecuteInTransactionAsync(Func asyncActi throw new DataStoreUpdateException(exception); } } + + [LoggerMessage(Level = LogLevel.Information, SkipEnabledCheck = true, Message = "Executing SQL: {LineBreak}{Query}")] + private partial void LogExecute(string lineBreak, string query); + + [LoggerMessage(Level = LogLevel.Information, SkipEnabledCheck = true, Message = "Executing SQL with parameters: {Parameters}{LineBreak}{Query}")] + private partial void LogExecuteWithParameters(string lineBreak, string query, string parameters); } diff --git a/src/Examples/DapperExample/Repositories/ResourceChangeDetector.cs b/src/Examples/DapperExample/Repositories/ResourceChangeDetector.cs index 1d9b998340..58f7579254 100644 --- a/src/Examples/DapperExample/Repositories/ResourceChangeDetector.cs +++ b/src/Examples/DapperExample/Repositories/ResourceChangeDetector.cs @@ -12,21 +12,20 @@ namespace DapperExample.Repositories; /// internal sealed class ResourceChangeDetector { - private readonly CollectionConverter _collectionConverter = new(); private readonly IDataModelService _dataModelService; private Dictionary _currentColumnValues = []; private Dictionary _newColumnValues = []; - private Dictionary> _currentRightResourcesByRelationship = []; - private Dictionary> _newRightResourcesByRelationship = []; + private Dictionary> _currentRightResourcesByRelationship = []; + private Dictionary> _newRightResourcesByRelationship = []; public ResourceType ResourceType { get; } public ResourceChangeDetector(ResourceType resourceType, IDataModelService dataModelService) { - ArgumentGuard.NotNull(resourceType); - ArgumentGuard.NotNull(dataModelService); + ArgumentNullException.ThrowIfNull(resourceType); + ArgumentNullException.ThrowIfNull(dataModelService); ResourceType = resourceType; _dataModelService = dataModelService; @@ -34,7 +33,7 @@ public ResourceChangeDetector(ResourceType resourceType, IDataModelService dataM public void CaptureCurrentValues(IIdentifiable resource) { - ArgumentGuard.NotNull(resource); + ArgumentNullException.ThrowIfNull(resource); AssertSameType(ResourceType, resource); _currentColumnValues = CaptureColumnValues(resource); @@ -43,7 +42,7 @@ public void CaptureCurrentValues(IIdentifiable resource) public void CaptureNewValues(IIdentifiable resource) { - ArgumentGuard.NotNull(resource); + ArgumentNullException.ThrowIfNull(resource); AssertSameType(ResourceType, resource); _newColumnValues = CaptureColumnValues(resource); @@ -62,14 +61,14 @@ public void CaptureNewValues(IIdentifiable resource) return columnValues; } - private Dictionary> CaptureRightResourcesByRelationship(IIdentifiable resource) + private Dictionary> CaptureRightResourcesByRelationship(IIdentifiable resource) { - Dictionary> relationshipValues = []; + Dictionary> relationshipValues = []; foreach (RelationshipAttribute relationship in ResourceType.Relationships) { object? rightValue = relationship.GetValue(resource); - HashSet rightResources = _collectionConverter.ExtractResources(rightValue).ToHashSet(IdentifiableComparer.Instance); + HashSet rightResources = CollectionConverter.Instance.ExtractResources(rightValue).ToHashSet(IdentifiableComparer.Instance); relationshipValues[relationship] = rightResources; } @@ -88,7 +87,7 @@ public void AssertIsNotClearingAnyRequiredToOneRelationships(string resourceName if (!foreignKey.IsNullable) { object? currentRightId = - _currentRightResourcesByRelationship.TryGetValue(hasOneRelationship, out ISet? currentRightResources) + _currentRightResourcesByRelationship.TryGetValue(hasOneRelationship, out HashSet? currentRightResources) ? currentRightResources.FirstOrDefault()?.GetTypedId() : null; @@ -118,7 +117,7 @@ public void AssertIsNotClearingAnyRequiredToOneRelationships(string resourceName if (newRightId != null) { object? currentRightId = - _currentRightResourcesByRelationship.TryGetValue(hasOneRelationship, out ISet? currentRightResources) + _currentRightResourcesByRelationship.TryGetValue(hasOneRelationship, out HashSet? currentRightResources) ? currentRightResources.FirstOrDefault()?.GetTypedId() : null; @@ -130,7 +129,7 @@ public void AssertIsNotClearingAnyRequiredToOneRelationships(string resourceName } } - return changes; + return changes.AsReadOnly(); } public IReadOnlyDictionary GetChangedColumnValues() @@ -147,7 +146,7 @@ public void AssertIsNotClearingAnyRequiredToOneRelationships(string resourceName } } - return changes; + return changes.AsReadOnly(); } public IReadOnlyDictionary GetChangedToOneRelationshipsWithForeignKeyAtRightSide() @@ -165,7 +164,7 @@ public void AssertIsNotClearingAnyRequiredToOneRelationships(string resourceName continue; } - object? currentRightId = _currentRightResourcesByRelationship.TryGetValue(hasOneRelationship, out ISet? currentRightResources) + object? currentRightId = _currentRightResourcesByRelationship.TryGetValue(hasOneRelationship, out HashSet? currentRightResources) ? currentRightResources.FirstOrDefault()?.GetTypedId() : null; @@ -178,7 +177,7 @@ public void AssertIsNotClearingAnyRequiredToOneRelationships(string resourceName } } - return changes; + return changes.AsReadOnly(); } public IReadOnlyDictionary currentRightIds, ISet newRightIds)> GetChangedToManyRelationships() @@ -192,7 +191,7 @@ public void AssertIsNotClearingAnyRequiredToOneRelationships(string resourceName HashSet newRightIds = newRightResources.Select(resource => resource.GetTypedId()).ToHashSet(); HashSet currentRightIds = - _currentRightResourcesByRelationship.TryGetValue(hasManyRelationship, out ISet? currentRightResources) + _currentRightResourcesByRelationship.TryGetValue(hasManyRelationship, out HashSet? currentRightResources) ? currentRightResources.Select(resource => resource.GetTypedId()).ToHashSet() : []; @@ -203,7 +202,7 @@ public void AssertIsNotClearingAnyRequiredToOneRelationships(string resourceName } } - return changes; + return changes.AsReadOnly(); } private static void AssertSameType(ResourceType resourceType, IIdentifiable resource) diff --git a/src/Examples/DapperExample/Repositories/ResultSetMapper.cs b/src/Examples/DapperExample/Repositories/ResultSetMapper.cs index 4352b6c552..89a7890fd0 100644 --- a/src/Examples/DapperExample/Repositories/ResultSetMapper.cs +++ b/src/Examples/DapperExample/Repositories/ResultSetMapper.cs @@ -18,9 +18,6 @@ internal sealed class ResultSetMapper // Note we don't do full bidirectional relationship fix-up; this just avoids duplicate instances. private readonly Dictionary> _resourceByTypeCache = []; - // Optimization to avoid unneeded calls to expensive Activator.CreateInstance() method, which is needed multiple times per row. - private readonly Dictionary _defaultValueByTypeCache = []; - // Used to determine where in the tree of included relationships a join object belongs to. private readonly Dictionary _includeElementToJoinObjectArrayIndexLookup = new(ReferenceEqualityComparer.Instance); @@ -114,22 +111,10 @@ public ResultSetMapper(IncludeExpression? include) private bool HasDefaultValue(object value) { - object? defaultValue = GetDefaultValueCached(value.GetType()); + object? defaultValue = RuntimeTypeConverter.GetDefaultValue(value.GetType()); return Equals(defaultValue, value); } - private object? GetDefaultValueCached(Type type) - { - if (_defaultValueByTypeCache.TryGetValue(type, out object? defaultValue)) - { - return defaultValue; - } - - defaultValue = RuntimeTypeConverter.GetDefaultValue(type); - _defaultValueByTypeCache[type] = defaultValue; - return defaultValue; - } - private void RecursiveSetRelationships(object leftResource, IEnumerable includeElements, object?[] joinObjects) { foreach (IncludeElementExpression includeElement in includeElements) @@ -139,7 +124,7 @@ private void RecursiveSetRelationships(object leftResource, IEnumerable 0) { RecursiveSetRelationships(rightResource, includeElement.Children, joinObjects); } @@ -163,7 +148,7 @@ private void SetRelationship(object leftResource, RelationshipAttribute relation public IReadOnlyCollection GetResources() { - return _primaryResourcesInOrder.DistinctBy(resource => resource.Id).ToList(); + return _primaryResourcesInOrder.DistinctBy(resource => resource.Id).ToArray().AsReadOnly(); } private sealed class IncludeElementWalker(IncludeExpression include) diff --git a/src/Examples/DapperExample/Repositories/SqlCaptureStore.cs b/src/Examples/DapperExample/Repositories/SqlCaptureStore.cs index 15d4e95d81..701f1ca740 100644 --- a/src/Examples/DapperExample/Repositories/SqlCaptureStore.cs +++ b/src/Examples/DapperExample/Repositories/SqlCaptureStore.cs @@ -11,7 +11,7 @@ public sealed class SqlCaptureStore { private readonly List _sqlCommands = []; - public IReadOnlyList SqlCommands => _sqlCommands; + public IReadOnlyList SqlCommands => _sqlCommands.AsReadOnly(); public void Clear() { diff --git a/src/Examples/DapperExample/SystemClock.cs b/src/Examples/DapperExample/SystemClock.cs deleted file mode 100644 index 3fed87c586..0000000000 --- a/src/Examples/DapperExample/SystemClock.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace DapperExample; - -public sealed class SystemClock : IClock -{ - public DateTimeOffset UtcNow => DateTimeOffset.UtcNow; -} diff --git a/src/Examples/DapperExample/TranslationToSql/Builders/DeleteOneToOneStatementBuilder.cs b/src/Examples/DapperExample/TranslationToSql/Builders/DeleteOneToOneStatementBuilder.cs index 3ea368b299..afd955dc62 100644 --- a/src/Examples/DapperExample/TranslationToSql/Builders/DeleteOneToOneStatementBuilder.cs +++ b/src/Examples/DapperExample/TranslationToSql/Builders/DeleteOneToOneStatementBuilder.cs @@ -1,17 +1,17 @@ using DapperExample.TranslationToSql.DataModel; using DapperExample.TranslationToSql.TreeNodes; -using JsonApiDotNetCore; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Queries.Expressions; namespace DapperExample.TranslationToSql.Builders; -internal sealed class DeleteOneToOneStatementBuilder(IDataModelService dataModelService) : StatementBuilder(dataModelService) +internal sealed class DeleteOneToOneStatementBuilder(IDataModelService dataModelService) + : StatementBuilder(dataModelService) { public DeleteNode Build(ResourceType resourceType, string whereColumnName, object? whereValue) { - ArgumentGuard.NotNull(resourceType); - ArgumentGuard.NotNull(whereColumnName); + ArgumentNullException.ThrowIfNull(resourceType); + ArgumentException.ThrowIfNullOrEmpty(whereColumnName); ResetState(); diff --git a/src/Examples/DapperExample/TranslationToSql/Builders/DeleteResourceStatementBuilder.cs b/src/Examples/DapperExample/TranslationToSql/Builders/DeleteResourceStatementBuilder.cs index 1910075a8c..b3afe4a2a4 100644 --- a/src/Examples/DapperExample/TranslationToSql/Builders/DeleteResourceStatementBuilder.cs +++ b/src/Examples/DapperExample/TranslationToSql/Builders/DeleteResourceStatementBuilder.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using DapperExample.TranslationToSql.DataModel; using DapperExample.TranslationToSql.TreeNodes; using JsonApiDotNetCore; @@ -6,11 +7,12 @@ namespace DapperExample.TranslationToSql.Builders; -internal sealed class DeleteResourceStatementBuilder(IDataModelService dataModelService) : StatementBuilder(dataModelService) +internal sealed class DeleteResourceStatementBuilder(IDataModelService dataModelService) + : StatementBuilder(dataModelService) { public DeleteNode Build(ResourceType resourceType, params object[] idValues) { - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(resourceType); ArgumentGuard.NotNullNorEmpty(idValues); ResetState(); @@ -25,7 +27,7 @@ public DeleteNode Build(ResourceType resourceType, params object[] idValues) private WhereNode GetWhere(ColumnNode idColumn, IEnumerable idValues) { - List parameters = idValues.Select(idValue => ParameterGenerator.Create(idValue)).ToList(); + ReadOnlyCollection parameters = idValues.Select(ParameterGenerator.Create).ToArray().AsReadOnly(); FilterNode filter = parameters.Count == 1 ? new ComparisonNode(ComparisonOperator.Equals, idColumn, parameters[0]) : new InNode(idColumn, parameters); return new WhereNode(filter); } diff --git a/src/Examples/DapperExample/TranslationToSql/Builders/InsertStatementBuilder.cs b/src/Examples/DapperExample/TranslationToSql/Builders/InsertStatementBuilder.cs index 5f8374df65..2f71cee112 100644 --- a/src/Examples/DapperExample/TranslationToSql/Builders/InsertStatementBuilder.cs +++ b/src/Examples/DapperExample/TranslationToSql/Builders/InsertStatementBuilder.cs @@ -1,27 +1,28 @@ +using System.Collections.ObjectModel; using DapperExample.TranslationToSql.DataModel; using DapperExample.TranslationToSql.TreeNodes; -using JsonApiDotNetCore; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Resources; namespace DapperExample.TranslationToSql.Builders; -internal sealed class InsertStatementBuilder(IDataModelService dataModelService) : StatementBuilder(dataModelService) +internal sealed class InsertStatementBuilder(IDataModelService dataModelService) + : StatementBuilder(dataModelService) { public InsertNode Build(ResourceType resourceType, IReadOnlyDictionary columnsToSet) { - ArgumentGuard.NotNull(resourceType); - ArgumentGuard.NotNull(columnsToSet); + ArgumentNullException.ThrowIfNull(resourceType); + ArgumentNullException.ThrowIfNull(columnsToSet); ResetState(); TableNode table = GetTable(resourceType, null); - List assignments = GetColumnAssignments(columnsToSet, table); + ReadOnlyCollection assignments = GetColumnAssignments(columnsToSet, table); return new InsertNode(table, assignments); } - private List GetColumnAssignments(IReadOnlyDictionary columnsToSet, TableNode table) + private ReadOnlyCollection GetColumnAssignments(IReadOnlyDictionary columnsToSet, TableNode table) { List assignments = []; ColumnNode idColumn = table.GetIdColumn(table.Alias); @@ -45,6 +46,6 @@ private List GetColumnAssignments(IReadOnlyDictionary columnMappings = _queryState.DataModelService.GetColumnMappings(resourceType); var table = new TableNode(resourceType, columnMappings, _queryState.TableAliasGenerator.GetNext()); @@ -194,8 +194,8 @@ private void SetColumnSelectors(TableAccessorNode tableAccessor, IEnumerable PreserveColumnOrderEnsuringUniqueNames(IEnumerable columns) @@ -213,7 +213,7 @@ private List PreserveColumnOrderEnsuringUniqueNames(IEnumerable OrderColumnsWithIdAtFrontEnsuringUniqueNames(IEnumerable columns) + private SelectorNode[] OrderColumnsWithIdAtFrontEnsuringUniqueNames(IEnumerable columns) { Dictionary> selectorsPerTable = []; @@ -236,7 +236,7 @@ private List OrderColumnsWithIdAtFrontEnsuringUniqueNames(IEnumera } } - return selectorsPerTable.SelectMany(selector => selector.Value).ToList(); + return selectorsPerTable.SelectMany(selector => selector.Value).ToArray(); } private string GetUniqueSelectorName(string columnName) @@ -260,7 +260,7 @@ private void ConvertNestedQueryLayer(TableAccessorNode tableAccessor, Relationsh { var subSelectBuilder = new SelectStatementBuilder(_queryState); - TableAccessorNode primaryTableAccessor = subSelectBuilder.CreatePrimaryTable(relationship.RightType); + FromNode primaryTableAccessor = subSelectBuilder.CreatePrimaryTable(relationship.RightType); subSelectBuilder.ConvertQueryLayer(nextLayer, primaryTableAccessor); string[] innerTableAliases = subSelectBuilder._selectorsPerTable.Keys.Select(accessor => accessor.Source.Alias).Cast().ToArray(); @@ -271,7 +271,7 @@ private void ConvertNestedQueryLayer(TableAccessorNode tableAccessor, Relationsh subSelectBuilder.SelectAllColumnsInAllTables(selectorsToKeep.Keys); // Since there's no pagination support, it's pointless to preserve orderings in the sub-query. - List orderingsToKeep = subSelectBuilder._orderByTerms.ToList(); + OrderByTermNode[] orderingsToKeep = subSelectBuilder._orderByTerms.ToArray(); subSelectBuilder._orderByTerms.Clear(); SelectNode aliasedSubQuery = subSelectBuilder.ToSelect(true, true); @@ -283,10 +283,11 @@ private void ConvertNestedQueryLayer(TableAccessorNode tableAccessor, Relationsh TableAccessorNode outerTableAccessor = CreateRelatedTable(tableAccessor, relationship, aliasedSubQuery); // In the outer query, select only what was originally selected. - _selectorsPerTable[outerTableAccessor] = MapSelectorsFromSubQuery(selectorsToKeep.SelectMany(selector => selector.Value), aliasedSubQuery); + _selectorsPerTable[outerTableAccessor] = + MapSelectorsFromSubQuery(selectorsToKeep.SelectMany(selector => selector.Value), aliasedSubQuery).AsReadOnly(); // To achieve total ordering, all orderings from sub-query must always appear in the root query. - IReadOnlyList outerOrderingsToAdd = MapOrderingsFromSubQuery(orderingsToKeep, aliasedSubQuery); + List outerOrderingsToAdd = MapOrderingsFromSubQuery(orderingsToKeep, aliasedSubQuery); _orderByTerms.AddRange(outerOrderingsToAdd); } else @@ -356,7 +357,7 @@ private void TrackRelatedTable(TableAccessorNode leftTableAccessor, Relationship _queryState.RelatedTables[leftTableAccessor].Add(relationship, rightTableAccessor); } - private IReadOnlyList MapSelectorsFromSubQuery(IEnumerable innerSelectorsToKeep, SelectNode select) + private List MapSelectorsFromSubQuery(IEnumerable innerSelectorsToKeep, SelectNode select) { List outerColumnsToKeep = []; @@ -379,7 +380,7 @@ private IReadOnlyList MapSelectorsFromSubQuery(IEnumerable MapOrderingsFromSubQuery(IEnumerable innerOrderingsToKeep, SelectNode select) + private List MapOrderingsFromSubQuery(IEnumerable innerOrderingsToKeep, SelectNode select) { List orderingsToKeep = []; @@ -419,9 +420,9 @@ private TableAccessorNode GetOrCreateRelatedTable(TableAccessorNode leftTableAcc return relatedTableAccessor; } - private TableAccessorNode CreatePrimaryTableWithIdentityCondition(TableSourceNode outerTableSource, RelationshipAttribute relationship) + private FromNode CreatePrimaryTableWithIdentityCondition(TableSourceNode outerTableSource, RelationshipAttribute relationship) { - TableAccessorNode innerTableAccessor = CreatePrimaryTable(relationship.RightType); + FromNode innerTableAccessor = CreatePrimaryTable(relationship.RightType); ComparisonNode joinCondition = CreateJoinCondition(outerTableSource, relationship, innerTableAccessor.Source); _whereFilters.Add(joinCondition); @@ -438,14 +439,14 @@ private TableAccessorNode CreatePrimaryTableWithIdentityCondition(TableSourceNod private SelectNode ToSelect(bool isSubQuery, bool createAlias) { WhereNode? where = GetWhere(); - OrderByNode? orderBy = !_orderByTerms.Any() ? null : new OrderByNode(_orderByTerms); + OrderByNode? orderBy = _orderByTerms.Count == 0 ? null : new OrderByNode(_orderByTerms.AsReadOnly()); // Materialization using Dapper requires selectors to match property names, so adjust selector names accordingly. Dictionary> selectorsPerTable = isSubQuery ? _selectorsPerTable : AliasSelectorsToTableColumnNames(_selectorsPerTable); string? alias = createAlias ? _queryState.TableAliasGenerator.GetNext() : null; - return new SelectNode(selectorsPerTable, where, orderBy, alias); + return new SelectNode(selectorsPerTable.AsReadOnly(), where, orderBy, alias); } private WhereNode? GetWhere() @@ -457,7 +458,7 @@ private SelectNode ToSelect(bool isSubQuery, bool createAlias) var combinator = new LogicalCombinator(); - FilterNode filter = _whereFilters.Count == 1 ? _whereFilters[0] : new LogicalNode(LogicalOperator.And, _whereFilters); + FilterNode filter = _whereFilters.Count == 1 ? _whereFilters[0] : new LogicalNode(LogicalOperator.And, _whereFilters.AsReadOnly()); FilterNode collapsed = combinator.Collapse(filter); return new WhereNode(collapsed); @@ -470,7 +471,7 @@ private static Dictionary> AliasS foreach ((TableAccessorNode tableAccessor, IReadOnlyList tableSelectors) in selectorsPerTable) { - aliasedSelectors[tableAccessor] = tableSelectors.Select(AliasToTableColumnName).ToList(); + aliasedSelectors[tableAccessor] = tableSelectors.Select(AliasToTableColumnName).ToArray().AsReadOnly(); } return aliasedSelectors; @@ -569,15 +570,15 @@ public override SqlTreeNode VisitLiteralConstant(LiteralConstantExpression expre public override SqlTreeNode VisitLogical(LogicalExpression expression, TableAccessorNode tableAccessor) { - FilterNode[] terms = VisitSequence(expression.Terms, tableAccessor).ToArray(); + ReadOnlyCollection terms = VisitSequence(expression.Terms, tableAccessor); return new LogicalNode(expression.Operator, terms); } - private IEnumerable VisitSequence(IEnumerable source, TableAccessorNode tableAccessor) + private ReadOnlyCollection VisitSequence(IEnumerable source, TableAccessorNode tableAccessor) where TIn : QueryExpression where TOut : SqlTreeNode { - return source.Select(expression => (TOut)Visit(expression, tableAccessor)).ToList(); + return source.Select(expression => (TOut)Visit(expression, tableAccessor)).ToArray().AsReadOnly(); } public override SqlTreeNode VisitNot(NotExpression expression, TableAccessorNode tableAccessor) @@ -588,12 +589,9 @@ public override SqlTreeNode VisitNot(NotExpression expression, TableAccessorNode var finder = new NullableAttributeFinder(_queryState.DataModelService); finder.Visit(expression, null); - if (finder.AttributesToNullCheck.Any()) + if (finder.AttributesToNullCheck.Count > 0) { - var orTerms = new List - { - filter - }; + List orTerms = [filter]; foreach (ResourceFieldChainExpression fieldChain in finder.AttributesToNullCheck) { @@ -602,7 +600,7 @@ public override SqlTreeNode VisitNot(NotExpression expression, TableAccessorNode orTerms.Add(isNullCheck); } - return new LogicalNode(LogicalOperator.Or, orTerms); + return new LogicalNode(LogicalOperator.Or, orTerms.AsReadOnly()); } return filter; @@ -656,7 +654,7 @@ public override SqlTreeNode VisitSortElement(SortElementExpression expression, T public override SqlTreeNode VisitSort(SortExpression expression, TableAccessorNode tableAccessor) { - OrderByTermNode[] terms = VisitSequence(expression.Elements, tableAccessor).ToArray(); + ReadOnlyCollection terms = VisitSequence(expression.Elements, tableAccessor); return new OrderByNode(terms); } @@ -688,21 +686,21 @@ public override SqlTreeNode VisitAny(AnyExpression expression, TableAccessorNode { var column = (ColumnNode)Visit(expression.TargetAttribute, tableAccessor); - ParameterNode[] parameters = - VisitSequence(expression.Constants.OrderBy(constant => constant.TypedValue), tableAccessor).ToArray(); + ReadOnlyCollection parameters = + VisitSequence(expression.Constants.OrderBy(constant => constant.TypedValue), tableAccessor); - return parameters.Length == 1 ? new ComparisonNode(ComparisonOperator.Equals, column, parameters[0]) : new InNode(column, parameters); + return parameters.Count == 1 ? new ComparisonNode(ComparisonOperator.Equals, column, parameters[0]) : new InNode(column, parameters); } private sealed class NullableAttributeFinder : QueryExpressionRewriter { private readonly IDataModelService _dataModelService; - public IList AttributesToNullCheck { get; } = new List(); + public List AttributesToNullCheck { get; } = []; public NullableAttributeFinder(IDataModelService dataModelService) { - ArgumentGuard.NotNull(dataModelService); + ArgumentNullException.ThrowIfNull(dataModelService); _dataModelService = dataModelService; } @@ -759,10 +757,10 @@ private sealed class QueryState public QueryState(IDataModelService dataModelService, TableAliasGenerator tableAliasGenerator, ParameterGenerator parameterGenerator, ILoggerFactory loggerFactory) { - ArgumentGuard.NotNull(dataModelService); - ArgumentGuard.NotNull(tableAliasGenerator); - ArgumentGuard.NotNull(parameterGenerator); - ArgumentGuard.NotNull(loggerFactory); + ArgumentNullException.ThrowIfNull(dataModelService); + ArgumentNullException.ThrowIfNull(tableAliasGenerator); + ArgumentNullException.ThrowIfNull(parameterGenerator); + ArgumentNullException.ThrowIfNull(loggerFactory); DataModelService = dataModelService; TableAliasGenerator = tableAliasGenerator; diff --git a/src/Examples/DapperExample/TranslationToSql/Builders/SqlQueryBuilder.cs b/src/Examples/DapperExample/TranslationToSql/Builders/SqlQueryBuilder.cs index a082d3ecad..5d3fc634da 100644 --- a/src/Examples/DapperExample/TranslationToSql/Builders/SqlQueryBuilder.cs +++ b/src/Examples/DapperExample/TranslationToSql/Builders/SqlQueryBuilder.cs @@ -1,6 +1,5 @@ using System.Text; using DapperExample.TranslationToSql.TreeNodes; -using JsonApiDotNetCore; using JsonApiDotNetCore.Queries.Expressions; namespace DapperExample.TranslationToSql.Builders; @@ -37,7 +36,7 @@ internal sealed class SqlQueryBuilder(DatabaseProvider databaseProvider) : SqlTr public string GetCommand(SqlTreeNode node) { - ArgumentGuard.NotNull(node); + ArgumentNullException.ThrowIfNull(node); ResetState(); @@ -307,7 +306,7 @@ private void WriteColumn(ColumnNode column, bool isVirtualColumn, StringBuilder { foreach (char specialCharacter in SpecialCharactersInLike) { - safeValue = safeValue.Replace(specialCharacter.ToString(), @"\" + specialCharacter); + safeValue = safeValue.Replace(specialCharacter.ToString(), $@"\{specialCharacter}"); } } @@ -477,7 +476,7 @@ internal static string FormatIdentifier(string value, DatabaseProvider databaseP }; } - private IDisposable Indent() + private RevertIndentOnDispose Indent() { _indentDepth++; return new RevertIndentOnDispose(this); diff --git a/src/Examples/DapperExample/TranslationToSql/Builders/StatementBuilder.cs b/src/Examples/DapperExample/TranslationToSql/Builders/StatementBuilder.cs index 06ebc1867f..de35ea5ba9 100644 --- a/src/Examples/DapperExample/TranslationToSql/Builders/StatementBuilder.cs +++ b/src/Examples/DapperExample/TranslationToSql/Builders/StatementBuilder.cs @@ -1,7 +1,6 @@ using DapperExample.TranslationToSql.DataModel; using DapperExample.TranslationToSql.Generators; using DapperExample.TranslationToSql.TreeNodes; -using JsonApiDotNetCore; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Resources.Annotations; @@ -15,7 +14,7 @@ internal abstract class StatementBuilder protected StatementBuilder(IDataModelService dataModelService) { - ArgumentGuard.NotNull(dataModelService); + ArgumentNullException.ThrowIfNull(dataModelService); _dataModelService = dataModelService; } diff --git a/src/Examples/DapperExample/TranslationToSql/Builders/UpdateClearOneToOneStatementBuilder.cs b/src/Examples/DapperExample/TranslationToSql/Builders/UpdateClearOneToOneStatementBuilder.cs index 712561528d..610ae9830d 100644 --- a/src/Examples/DapperExample/TranslationToSql/Builders/UpdateClearOneToOneStatementBuilder.cs +++ b/src/Examples/DapperExample/TranslationToSql/Builders/UpdateClearOneToOneStatementBuilder.cs @@ -1,18 +1,18 @@ using DapperExample.TranslationToSql.DataModel; using DapperExample.TranslationToSql.TreeNodes; -using JsonApiDotNetCore; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Queries.Expressions; namespace DapperExample.TranslationToSql.Builders; -internal sealed class UpdateClearOneToOneStatementBuilder(IDataModelService dataModelService) : StatementBuilder(dataModelService) +internal sealed class UpdateClearOneToOneStatementBuilder(IDataModelService dataModelService) + : StatementBuilder(dataModelService) { public UpdateNode Build(ResourceType resourceType, string setColumnName, string whereColumnName, object? whereValue) { - ArgumentGuard.NotNull(resourceType); - ArgumentGuard.NotNull(setColumnName); - ArgumentGuard.NotNull(whereColumnName); + ArgumentNullException.ThrowIfNull(resourceType); + ArgumentException.ThrowIfNullOrEmpty(setColumnName); + ArgumentException.ThrowIfNullOrEmpty(whereColumnName); ResetState(); diff --git a/src/Examples/DapperExample/TranslationToSql/Builders/UpdateResourceStatementBuilder.cs b/src/Examples/DapperExample/TranslationToSql/Builders/UpdateResourceStatementBuilder.cs index a279ad45e5..619dba7797 100644 --- a/src/Examples/DapperExample/TranslationToSql/Builders/UpdateResourceStatementBuilder.cs +++ b/src/Examples/DapperExample/TranslationToSql/Builders/UpdateResourceStatementBuilder.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using DapperExample.TranslationToSql.DataModel; using DapperExample.TranslationToSql.TreeNodes; using JsonApiDotNetCore; @@ -6,18 +7,19 @@ namespace DapperExample.TranslationToSql.Builders; -internal sealed class UpdateResourceStatementBuilder(IDataModelService dataModelService) : StatementBuilder(dataModelService) +internal sealed class UpdateResourceStatementBuilder(IDataModelService dataModelService) + : StatementBuilder(dataModelService) { public UpdateNode Build(ResourceType resourceType, IReadOnlyDictionary columnsToUpdate, params object[] idValues) { - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(resourceType); ArgumentGuard.NotNullNorEmpty(columnsToUpdate); ArgumentGuard.NotNullNorEmpty(idValues); ResetState(); TableNode table = GetTable(resourceType, null); - List assignments = GetColumnAssignments(columnsToUpdate, table); + ReadOnlyCollection assignments = GetColumnAssignments(columnsToUpdate, table); ColumnNode idColumn = table.GetIdColumn(table.Alias); WhereNode where = GetWhere(idColumn, idValues); @@ -25,7 +27,7 @@ public UpdateNode Build(ResourceType resourceType, IReadOnlyDictionary GetColumnAssignments(IReadOnlyDictionary columnsToUpdate, TableNode table) + private ReadOnlyCollection GetColumnAssignments(IReadOnlyDictionary columnsToUpdate, TableNode table) { List assignments = []; @@ -38,12 +40,12 @@ private List GetColumnAssignments(IReadOnlyDictionary idValues) { - List parameters = idValues.Select(idValue => ParameterGenerator.Create(idValue)).ToList(); + ReadOnlyCollection parameters = idValues.Select(ParameterGenerator.Create).ToArray().AsReadOnly(); FilterNode filter = parameters.Count == 1 ? new ComparisonNode(ComparisonOperator.Equals, idColumn, parameters[0]) : new InNode(idColumn, parameters); return new WhereNode(filter); } diff --git a/src/Examples/DapperExample/TranslationToSql/DataModel/BaseDataModelService.cs b/src/Examples/DapperExample/TranslationToSql/DataModel/BaseDataModelService.cs index 589852ad80..3c752ffcbd 100644 --- a/src/Examples/DapperExample/TranslationToSql/DataModel/BaseDataModelService.cs +++ b/src/Examples/DapperExample/TranslationToSql/DataModel/BaseDataModelService.cs @@ -1,10 +1,10 @@ +using System.Collections.ObjectModel; using System.ComponentModel.DataAnnotations.Schema; using System.Data; using System.Data.Common; using System.Reflection; using Dapper; using DapperExample.TranslationToSql.TreeNodes; -using JsonApiDotNetCore; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; @@ -16,7 +16,7 @@ namespace DapperExample.TranslationToSql.DataModel; /// public abstract class BaseDataModelService : IDataModelService { - private readonly Dictionary> _columnMappingsByType = []; + private readonly Dictionary> _columnMappingsByType = []; protected IResourceGraph ResourceGraph { get; } @@ -24,7 +24,7 @@ public abstract class BaseDataModelService : IDataModelService protected BaseDataModelService(IResourceGraph resourceGraph) { - ArgumentGuard.NotNull(resourceGraph); + ArgumentNullException.ThrowIfNull(resourceGraph); ResourceGraph = resourceGraph; } @@ -52,7 +52,7 @@ private void ScanColumnMappings() } } - private IReadOnlyDictionary ScanColumnMappings(ResourceType resourceType) + private ReadOnlyDictionary ScanColumnMappings(ResourceType resourceType) { Dictionary mappings = []; @@ -93,7 +93,7 @@ private void ScanColumnMappings() mappings[columnName] = field; } - return mappings; + return mappings.AsReadOnly(); } private static bool IsMapped(PropertyInfo property) @@ -103,7 +103,7 @@ private static bool IsMapped(PropertyInfo property) public IReadOnlyDictionary GetColumnMappings(ResourceType resourceType) { - if (_columnMappingsByType.TryGetValue(resourceType, out IReadOnlyDictionary? columnMappings)) + if (_columnMappingsByType.TryGetValue(resourceType, out ReadOnlyDictionary? columnMappings)) { return columnMappings; } @@ -113,10 +113,10 @@ private static bool IsMapped(PropertyInfo property) public object? GetColumnValue(ResourceType resourceType, IIdentifiable resource, string columnName) { - ArgumentGuard.NotNull(resourceType); - ArgumentGuard.NotNull(resource); + ArgumentNullException.ThrowIfNull(resourceType); + ArgumentNullException.ThrowIfNull(resource); AssertSameType(resourceType, resource); - ArgumentGuard.NotNullNorEmpty(columnName); + ArgumentException.ThrowIfNullOrEmpty(columnName); IReadOnlyDictionary columnMappings = GetColumnMappings(resourceType); diff --git a/src/Examples/DapperExample/TranslationToSql/DataModel/FromEntitiesDataModelService.cs b/src/Examples/DapperExample/TranslationToSql/DataModel/FromEntitiesDataModelService.cs index 711ad8517c..53bf5e4ae4 100644 --- a/src/Examples/DapperExample/TranslationToSql/DataModel/FromEntitiesDataModelService.cs +++ b/src/Examples/DapperExample/TranslationToSql/DataModel/FromEntitiesDataModelService.cs @@ -12,7 +12,8 @@ namespace DapperExample.TranslationToSql.DataModel; /// /// Derives foreign keys and connection strings from an existing Entity Framework Core model. /// -public sealed class FromEntitiesDataModelService(IResourceGraph resourceGraph) : BaseDataModelService(resourceGraph) +public sealed class FromEntitiesDataModelService(IResourceGraph resourceGraph) + : BaseDataModelService(resourceGraph) { private readonly Dictionary _foreignKeysByRelationship = []; private readonly Dictionary _columnNullabilityPerAttribute = []; diff --git a/src/Examples/DapperExample/TranslationToSql/DataModel/RelationshipForeignKey.cs b/src/Examples/DapperExample/TranslationToSql/DataModel/RelationshipForeignKey.cs index 6f5572001a..94633a9c36 100644 --- a/src/Examples/DapperExample/TranslationToSql/DataModel/RelationshipForeignKey.cs +++ b/src/Examples/DapperExample/TranslationToSql/DataModel/RelationshipForeignKey.cs @@ -2,7 +2,6 @@ using DapperExample.TranslationToSql.Builders; using Humanizer; using JetBrains.Annotations; -using JsonApiDotNetCore; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Resources.Annotations; @@ -38,8 +37,8 @@ public sealed class RelationshipForeignKey public RelationshipForeignKey(DatabaseProvider databaseProvider, RelationshipAttribute relationship, bool isAtLeftSide, string columnName, bool isNullable) { - ArgumentGuard.NotNull(relationship); - ArgumentGuard.NotNullNorEmpty(columnName); + ArgumentNullException.ThrowIfNull(relationship); + ArgumentException.ThrowIfNullOrEmpty(columnName); _databaseProvider = databaseProvider; Relationship = relationship; diff --git a/src/Examples/DapperExample/TranslationToSql/Generators/ParameterGenerator.cs b/src/Examples/DapperExample/TranslationToSql/Generators/ParameterGenerator.cs index aaa328e68f..577f1d2e3e 100644 --- a/src/Examples/DapperExample/TranslationToSql/Generators/ParameterGenerator.cs +++ b/src/Examples/DapperExample/TranslationToSql/Generators/ParameterGenerator.cs @@ -20,5 +20,6 @@ public void Reset() _nameGenerator.Reset(); } - private sealed class ParameterNameGenerator() : UniqueNameGenerator("@p"); + private sealed class ParameterNameGenerator() + : UniqueNameGenerator("@p"); } diff --git a/src/Examples/DapperExample/TranslationToSql/Generators/TableAliasGenerator.cs b/src/Examples/DapperExample/TranslationToSql/Generators/TableAliasGenerator.cs index a63bfdc01a..ff302caf10 100644 --- a/src/Examples/DapperExample/TranslationToSql/Generators/TableAliasGenerator.cs +++ b/src/Examples/DapperExample/TranslationToSql/Generators/TableAliasGenerator.cs @@ -3,4 +3,5 @@ namespace DapperExample.TranslationToSql.Generators; /// /// Generates a SQL table alias with a unique name. /// -internal sealed class TableAliasGenerator() : UniqueNameGenerator("t"); +internal sealed class TableAliasGenerator() + : UniqueNameGenerator("t"); diff --git a/src/Examples/DapperExample/TranslationToSql/Generators/UniqueNameGenerator.cs b/src/Examples/DapperExample/TranslationToSql/Generators/UniqueNameGenerator.cs index 3ea42ab529..5254f4a024 100644 --- a/src/Examples/DapperExample/TranslationToSql/Generators/UniqueNameGenerator.cs +++ b/src/Examples/DapperExample/TranslationToSql/Generators/UniqueNameGenerator.cs @@ -1,5 +1,3 @@ -using JsonApiDotNetCore; - namespace DapperExample.TranslationToSql.Generators; internal abstract class UniqueNameGenerator @@ -9,7 +7,7 @@ internal abstract class UniqueNameGenerator protected UniqueNameGenerator(string prefix) { - ArgumentGuard.NotNullNorEmpty(prefix); + ArgumentException.ThrowIfNullOrEmpty(prefix); _prefix = prefix; } diff --git a/src/Examples/DapperExample/TranslationToSql/SqlCommand.cs b/src/Examples/DapperExample/TranslationToSql/SqlCommand.cs index 37ed2d3ea5..735da0a55f 100644 --- a/src/Examples/DapperExample/TranslationToSql/SqlCommand.cs +++ b/src/Examples/DapperExample/TranslationToSql/SqlCommand.cs @@ -1,5 +1,4 @@ using JetBrains.Annotations; -using JsonApiDotNetCore; namespace DapperExample.TranslationToSql; @@ -14,8 +13,8 @@ public sealed class SqlCommand internal SqlCommand(string statement, IDictionary parameters) { - ArgumentGuard.NotNull(statement); - ArgumentGuard.NotNull(parameters); + ArgumentNullException.ThrowIfNull(statement); + ArgumentNullException.ThrowIfNull(parameters); Statement = statement; Parameters = parameters; diff --git a/src/Examples/DapperExample/TranslationToSql/Transformations/ColumnSelectorUsageCollector.cs b/src/Examples/DapperExample/TranslationToSql/Transformations/ColumnSelectorUsageCollector.cs index b5d560448c..e7c7799700 100644 --- a/src/Examples/DapperExample/TranslationToSql/Transformations/ColumnSelectorUsageCollector.cs +++ b/src/Examples/DapperExample/TranslationToSql/Transformations/ColumnSelectorUsageCollector.cs @@ -1,12 +1,11 @@ using DapperExample.TranslationToSql.TreeNodes; -using JsonApiDotNetCore; namespace DapperExample.TranslationToSql.Transformations; /// /// Collects all s in selectors that are referenced elsewhere in the query. /// -internal sealed class ColumnSelectorUsageCollector : SqlTreeNodeVisitor +internal sealed partial class ColumnSelectorUsageCollector : SqlTreeNodeVisitor { private readonly HashSet _usedColumns = []; private readonly ILogger _logger; @@ -15,21 +14,21 @@ internal sealed class ColumnSelectorUsageCollector : SqlTreeNodeVisitor(); } public void Collect(SelectNode select) { - ArgumentGuard.NotNull(select); + ArgumentNullException.ThrowIfNull(select); - _logger.LogDebug("Started collection of used columns."); + LogStarted(); _usedColumns.Clear(); InnerVisit(select, ColumnVisitMode.Reference); - _logger.LogDebug("Finished collection of used columns."); + LogFinished(); } public override object? VisitSelect(SelectNode node, ColumnVisitMode mode) @@ -70,7 +69,7 @@ public void Collect(SelectNode select) if (mode == ColumnVisitMode.Reference) { _usedColumns.Add(node.Column); - _logger.LogDebug($"Added used column {node.Column}."); + LogColumnAdded(node.Column); } InnerVisit(node.Column, mode); @@ -160,4 +159,13 @@ private void VisitSequence(IEnumerable nodes, ColumnVisitMode mode) InnerVisit(node, mode); } } + + [LoggerMessage(Level = LogLevel.Debug, Message = "Started collection of used columns.")] + private partial void LogStarted(); + + [LoggerMessage(Level = LogLevel.Debug, Message = "Finished collection of used columns.")] + private partial void LogFinished(); + + [LoggerMessage(Level = LogLevel.Debug, Message = "Added used column {Column}.")] + private partial void LogColumnAdded(ColumnNode column); } diff --git a/src/Examples/DapperExample/TranslationToSql/Transformations/LogicalCombinator.cs b/src/Examples/DapperExample/TranslationToSql/Transformations/LogicalCombinator.cs index 0fcd047a3d..95359462f7 100644 --- a/src/Examples/DapperExample/TranslationToSql/Transformations/LogicalCombinator.cs +++ b/src/Examples/DapperExample/TranslationToSql/Transformations/LogicalCombinator.cs @@ -14,7 +14,7 @@ public FilterNode Collapse(FilterNode filter) public override SqlTreeNode VisitLogical(LogicalNode node, object? argument) { - var newTerms = new List(); + List newTerms = []; foreach (FilterNode newTerm in node.Terms.Select(TypedVisit)) { @@ -28,7 +28,7 @@ public override SqlTreeNode VisitLogical(LogicalNode node, object? argument) } } - return new LogicalNode(node.Operator, newTerms); + return new LogicalNode(node.Operator, newTerms.AsReadOnly()); } public override SqlTreeNode DefaultVisit(SqlTreeNode node, object? argument) diff --git a/src/Examples/DapperExample/TranslationToSql/Transformations/StaleColumnReferenceRewriter.cs b/src/Examples/DapperExample/TranslationToSql/Transformations/StaleColumnReferenceRewriter.cs index a632c43e51..e364203684 100644 --- a/src/Examples/DapperExample/TranslationToSql/Transformations/StaleColumnReferenceRewriter.cs +++ b/src/Examples/DapperExample/TranslationToSql/Transformations/StaleColumnReferenceRewriter.cs @@ -1,6 +1,6 @@ +using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; using DapperExample.TranslationToSql.TreeNodes; -using JsonApiDotNetCore; namespace DapperExample.TranslationToSql.Transformations; @@ -28,7 +28,7 @@ namespace DapperExample.TranslationToSql.Transformations; ///

/// The reference to t1 in the WHERE clause has become stale and needs to be pulled out into scope, which is t2. /// -internal sealed class StaleColumnReferenceRewriter : SqlTreeNodeVisitor +internal sealed partial class StaleColumnReferenceRewriter : SqlTreeNodeVisitor { private readonly IReadOnlyDictionary _oldToNewTableAliasMap; private readonly ILogger _logger; @@ -36,8 +36,8 @@ internal sealed class StaleColumnReferenceRewriter : SqlTreeNodeVisitor oldToNewTableAliasMap, ILoggerFactory loggerFactory) { - ArgumentGuard.NotNull(oldToNewTableAliasMap); - ArgumentGuard.NotNull(loggerFactory); + ArgumentNullException.ThrowIfNull(oldToNewTableAliasMap); + ArgumentNullException.ThrowIfNull(loggerFactory); _oldToNewTableAliasMap = oldToNewTableAliasMap; _logger = loggerFactory.CreateLogger(); @@ -59,12 +59,13 @@ public override SqlTreeNode VisitSelect(SelectNode node, ColumnVisitMode mode) { IncludeTableAliasInCurrentScope(node); - using IDisposable scope = EnterSelectScope(); - - IReadOnlyDictionary> selectors = VisitSelectors(node.Selectors, mode); - WhereNode? where = TypedVisit(node.Where, mode); - OrderByNode? orderBy = TypedVisit(node.OrderBy, mode); - return new SelectNode(selectors, where, orderBy, node.Alias); + using (EnterSelectScope()) + { + ReadOnlyDictionary> selectors = VisitSelectors(node.Selectors, mode); + WhereNode? where = TypedVisit(node.Where, mode); + OrderByNode? orderBy = TypedVisit(node.OrderBy, mode); + return new SelectNode(selectors, where, orderBy, node.Alias); + } } private void IncludeTableAliasInCurrentScope(TableSourceNode tableSource) @@ -76,7 +77,7 @@ private void IncludeTableAliasInCurrentScope(TableSourceNode tableSource) } } - private IDisposable EnterSelectScope() + private PopStackOnDispose> EnterSelectScope() { Dictionary newScope = CopyTopStackElement(); _tablesInScopeStack.Push(newScope); @@ -95,7 +96,7 @@ private Dictionary CopyTopStackElement() return new Dictionary(topElement); } - private IReadOnlyDictionary> VisitSelectors( + private ReadOnlyDictionary> VisitSelectors( IReadOnlyDictionary> selectors, ColumnVisitMode mode) { Dictionary> newSelectors = []; @@ -103,12 +104,12 @@ private IReadOnlyDictionary> Visi foreach ((TableAccessorNode tableAccessor, IReadOnlyList tableSelectors) in selectors) { TableAccessorNode newTableAccessor = TypedVisit(tableAccessor, mode); - IReadOnlyList newTableSelectors = VisitList(tableSelectors, ColumnVisitMode.Declaration); + ReadOnlyCollection newTableSelectors = VisitSequence(tableSelectors, ColumnVisitMode.Declaration); newSelectors.Add(newTableAccessor, newTableSelectors); } - return newSelectors; + return newSelectors.AsReadOnly(); } public override SqlTreeNode VisitTable(TableNode node, ColumnVisitMode mode) @@ -142,7 +143,7 @@ public override SqlTreeNode VisitColumnInTable(ColumnInTableNode node, ColumnVis return MapColumnInTable(node, tablesInScope); } - private ColumnNode MapColumnInTable(ColumnInTableNode column, IDictionary tablesInScope) + private ColumnNode MapColumnInTable(ColumnInTableNode column, Dictionary tablesInScope) { if (column.TableAlias != null && !tablesInScope.ContainsKey(column.TableAlias)) { @@ -159,7 +160,7 @@ private ColumnNode MapColumnInTable(ColumnInTableNode column, IDictionary terms = VisitList(node.Terms, mode); + ReadOnlyCollection terms = VisitSequence(node.Terms, mode); return new LogicalNode(node.Operator, terms); } @@ -233,7 +234,7 @@ public override SqlTreeNode VisitLike(LikeNode node, ColumnVisitMode mode) public override SqlTreeNode VisitIn(InNode node, ColumnVisitMode mode) { ColumnNode column = TypedVisit(node.Column, mode); - IReadOnlyList values = VisitList(node.Values, mode); + ReadOnlyCollection values = VisitSequence(node.Values, mode); return new InNode(column, values); } @@ -251,7 +252,7 @@ public override SqlTreeNode VisitCount(CountNode node, ColumnVisitMode mode) public override SqlTreeNode VisitOrderBy(OrderByNode node, ColumnVisitMode mode) { - IReadOnlyList terms = VisitList(node.Terms, mode); + ReadOnlyCollection terms = VisitSequence(node.Terms, mode); return new OrderByNode(terms); } @@ -277,19 +278,22 @@ public override SqlTreeNode VisitNullConstant(NullConstantNode node, ColumnVisit return node; } - [return: NotNullIfNotNull("node")] + [return: NotNullIfNotNull(nameof(node))] private T? TypedVisit(T? node, ColumnVisitMode mode) where T : SqlTreeNode { return node != null ? (T)Visit(node, mode) : null; } - private IReadOnlyList VisitList(IEnumerable nodes, ColumnVisitMode mode) + private ReadOnlyCollection VisitSequence(IEnumerable nodes, ColumnVisitMode mode) where T : SqlTreeNode { - return nodes.Select(element => TypedVisit(element, mode)).ToList(); + return nodes.Select(element => TypedVisit(element, mode)).ToArray().AsReadOnly(); } + [LoggerMessage(Level = LogLevel.Debug, Message = "Mapped inaccessible column {FromColumn} to {ToColumn}.")] + private partial void LogColumnMapped(ColumnNode fromColumn, ColumnNode toColumn); + private sealed class PopStackOnDispose(Stack stack) : IDisposable { private readonly Stack _stack = stack; diff --git a/src/Examples/DapperExample/TranslationToSql/Transformations/UnusedSelectorsRewriter.cs b/src/Examples/DapperExample/TranslationToSql/Transformations/UnusedSelectorsRewriter.cs index 7cffc8e29a..fe0f326209 100644 --- a/src/Examples/DapperExample/TranslationToSql/Transformations/UnusedSelectorsRewriter.cs +++ b/src/Examples/DapperExample/TranslationToSql/Transformations/UnusedSelectorsRewriter.cs @@ -1,6 +1,6 @@ +using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; using DapperExample.TranslationToSql.TreeNodes; -using JsonApiDotNetCore; namespace DapperExample.TranslationToSql.Transformations; @@ -26,7 +26,7 @@ namespace DapperExample.TranslationToSql.Transformations; ///

/// The selectors t1."AccountId" and t1."FirstName" have no references and can be removed. /// -internal sealed class UnusedSelectorsRewriter : SqlTreeNodeVisitor, SqlTreeNode> +internal sealed partial class UnusedSelectorsRewriter : SqlTreeNodeVisitor, SqlTreeNode> { private readonly ColumnSelectorUsageCollector _usageCollector; private readonly ILogger _logger; @@ -35,7 +35,7 @@ internal sealed class UnusedSelectorsRewriter : SqlTreeNodeVisitor(); @@ -43,7 +43,7 @@ public UnusedSelectorsRewriter(ILoggerFactory loggerFactory) public SelectNode RemoveUnusedSelectorsInSubQueries(SelectNode select) { - ArgumentGuard.NotNull(select); + ArgumentNullException.ThrowIfNull(select); _rootSelect = select; @@ -52,9 +52,9 @@ public SelectNode RemoveUnusedSelectorsInSubQueries(SelectNode select) _hasChanged = false; _usageCollector.Collect(_rootSelect); - _logger.LogDebug("Started removal of unused selectors."); + LogStarted(); _rootSelect = TypedVisit(_rootSelect, _usageCollector.UsedColumns); - _logger.LogDebug("Finished removal of unused selectors."); + LogFinished(); } while (_hasChanged); @@ -68,13 +68,13 @@ public override SqlTreeNode DefaultVisit(SqlTreeNode node, ISet used public override SqlTreeNode VisitSelect(SelectNode node, ISet usedColumns) { - IReadOnlyDictionary> selectors = VisitSelectors(node, usedColumns); + ReadOnlyDictionary> selectors = VisitSelectors(node, usedColumns); WhereNode? where = TypedVisit(node.Where, usedColumns); OrderByNode? orderBy = TypedVisit(node.OrderBy, usedColumns); return new SelectNode(selectors, where, orderBy, node.Alias); } - private IReadOnlyDictionary> VisitSelectors(SelectNode select, ISet usedColumns) + private ReadOnlyDictionary> VisitSelectors(SelectNode select, ISet usedColumns) { Dictionary> newSelectors = []; @@ -85,10 +85,10 @@ private IReadOnlyDictionary> Visi newSelectors.Add(newTableAccessor, newTableSelectors); } - return newSelectors; + return newSelectors.AsReadOnly(); } - private List VisitTableSelectors(IEnumerable selectors, ISet usedColumns) + private ReadOnlyCollection VisitTableSelectors(IEnumerable selectors, ISet usedColumns) { List newTableSelectors = []; @@ -98,7 +98,7 @@ private List VisitTableSelectors(IEnumerable selecto { if (!usedColumns.Contains(columnSelector.Column)) { - _logger.LogDebug($"Removing unused selector {columnSelector}."); + LogSelectorRemoved(columnSelector); _hasChanged = true; continue; } @@ -107,7 +107,7 @@ private List VisitTableSelectors(IEnumerable selecto newTableSelectors.Add(selector); } - return newTableSelectors; + return newTableSelectors.AsReadOnly(); } public override SqlTreeNode VisitFrom(FromNode node, ISet usedColumns) @@ -150,7 +150,7 @@ public override SqlTreeNode VisitNot(NotNode node, ISet usedColumns) public override SqlTreeNode VisitLogical(LogicalNode node, ISet usedColumns) { - IReadOnlyList terms = VisitList(node.Terms, usedColumns); + ReadOnlyCollection terms = VisitSequence(node.Terms, usedColumns); return new LogicalNode(node.Operator, terms); } @@ -170,7 +170,7 @@ public override SqlTreeNode VisitLike(LikeNode node, ISet usedColumn public override SqlTreeNode VisitIn(InNode node, ISet usedColumns) { ColumnNode column = TypedVisit(node.Column, usedColumns); - IReadOnlyList values = VisitList(node.Values, usedColumns); + ReadOnlyCollection values = VisitSequence(node.Values, usedColumns); return new InNode(column, values); } @@ -188,7 +188,7 @@ public override SqlTreeNode VisitCount(CountNode node, ISet usedColu public override SqlTreeNode VisitOrderBy(OrderByNode node, ISet usedColumns) { - IReadOnlyList terms = VisitList(node.Terms, usedColumns); + ReadOnlyCollection terms = VisitSequence(node.Terms, usedColumns); return new OrderByNode(terms); } @@ -204,16 +204,25 @@ public override SqlTreeNode VisitOrderByCount(OrderByCountNode node, ISet(T? node, ISet usedColumns) where T : SqlTreeNode { return node != null ? (T)Visit(node, usedColumns) : null; } - private IReadOnlyList VisitList(IEnumerable nodes, ISet usedColumns) + private ReadOnlyCollection VisitSequence(IEnumerable nodes, ISet usedColumns) where T : SqlTreeNode { - return nodes.Select(element => TypedVisit(element, usedColumns)).ToList(); + return nodes.Select(element => TypedVisit(element, usedColumns)).ToArray().AsReadOnly(); } + + [LoggerMessage(Level = LogLevel.Debug, Message = "Started removal of unused selectors.")] + private partial void LogStarted(); + + [LoggerMessage(Level = LogLevel.Debug, Message = "Finished removal of unused selectors.")] + private partial void LogFinished(); + + [LoggerMessage(Level = LogLevel.Debug, Message = "Removing unused selector {Selector}.")] + private partial void LogSelectorRemoved(ColumnSelectorNode selector); } diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/ColumnAssignmentNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/ColumnAssignmentNode.cs index 1884dc8dbf..3578ea9a55 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/ColumnAssignmentNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/ColumnAssignmentNode.cs @@ -1,5 +1,3 @@ -using JsonApiDotNetCore; - namespace DapperExample.TranslationToSql.TreeNodes; /// @@ -17,8 +15,8 @@ internal sealed class ColumnAssignmentNode : SqlTreeNode public ColumnAssignmentNode(ColumnNode column, SqlValueNode value) { - ArgumentGuard.NotNull(column); - ArgumentGuard.NotNull(value); + ArgumentNullException.ThrowIfNull(column); + ArgumentNullException.ThrowIfNull(value); Column = column; Value = value; diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/ColumnInSelectNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/ColumnInSelectNode.cs index 2be0561011..14d82bb1d3 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/ColumnInSelectNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/ColumnInSelectNode.cs @@ -1,5 +1,3 @@ -using JsonApiDotNetCore; - namespace DapperExample.TranslationToSql.TreeNodes; /// @@ -10,8 +8,8 @@ namespace DapperExample.TranslationToSql.TreeNodes; /// SELECT t2.Id AS Id0 FROM (SELECT t1.Id FROM Users AS t1) AS t2 /// ]]>. /// -internal sealed class ColumnInSelectNode(ColumnSelectorNode selector, string? tableAlias) : ColumnNode(GetColumnName(selector), selector.Column.Type, - tableAlias) +internal sealed class ColumnInSelectNode(ColumnSelectorNode selector, string? tableAlias) + : ColumnNode(GetColumnName(selector), selector.Column.Type, tableAlias) { public ColumnSelectorNode Selector { get; } = selector; @@ -19,7 +17,7 @@ internal sealed class ColumnInSelectNode(ColumnSelectorNode selector, string? ta private static string GetColumnName(ColumnSelectorNode selector) { - ArgumentGuard.NotNull(selector); + ArgumentNullException.ThrowIfNull(selector); return selector.Identity; } diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/ColumnInTableNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/ColumnInTableNode.cs index cd605e72a4..da29ed97fc 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/ColumnInTableNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/ColumnInTableNode.cs @@ -8,7 +8,8 @@ namespace DapperExample.TranslationToSql.TreeNodes; /// FROM Users AS t1 /// ]]>. /// -internal sealed class ColumnInTableNode(string name, ColumnType type, string? tableAlias) : ColumnNode(name, type, tableAlias) +internal sealed class ColumnInTableNode(string name, ColumnType type, string? tableAlias) + : ColumnNode(name, type, tableAlias) { public override TResult Accept(SqlTreeNodeVisitor visitor, TArgument argument) { diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/ColumnNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/ColumnNode.cs index e4fbcf14e6..da348882a9 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/ColumnNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/ColumnNode.cs @@ -1,5 +1,3 @@ -using JsonApiDotNetCore; - namespace DapperExample.TranslationToSql.TreeNodes; /// @@ -13,7 +11,7 @@ internal abstract class ColumnNode : SqlValueNode protected ColumnNode(string name, ColumnType type, string? tableAlias) { - ArgumentGuard.NotNullNorEmpty(name); + ArgumentException.ThrowIfNullOrEmpty(name); Name = name; Type = type; diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/ColumnSelectorNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/ColumnSelectorNode.cs index ab2ab1031f..6c8bb9e36a 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/ColumnSelectorNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/ColumnSelectorNode.cs @@ -1,5 +1,3 @@ -using JsonApiDotNetCore; - namespace DapperExample.TranslationToSql.TreeNodes; /// @@ -19,7 +17,7 @@ internal sealed class ColumnSelectorNode : SelectorNode public ColumnSelectorNode(ColumnNode column, string? alias) : base(alias) { - ArgumentGuard.NotNull(column); + ArgumentNullException.ThrowIfNull(column); Column = column; } diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/ComparisonNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/ComparisonNode.cs index dbf61d5451..7264189a6d 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/ComparisonNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/ComparisonNode.cs @@ -1,4 +1,3 @@ -using JsonApiDotNetCore; using JsonApiDotNetCore.Queries.Expressions; namespace DapperExample.TranslationToSql.TreeNodes; @@ -16,8 +15,8 @@ internal sealed class ComparisonNode : FilterNode public ComparisonNode(ComparisonOperator @operator, SqlValueNode left, SqlValueNode right) { - ArgumentGuard.NotNull(left); - ArgumentGuard.NotNull(right); + ArgumentNullException.ThrowIfNull(left); + ArgumentNullException.ThrowIfNull(right); Operator = @operator; Left = left; diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/CountNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/CountNode.cs index 07182d036f..9133969961 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/CountNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/CountNode.cs @@ -1,5 +1,3 @@ -using JsonApiDotNetCore; - namespace DapperExample.TranslationToSql.TreeNodes; /// @@ -16,7 +14,7 @@ internal sealed class CountNode : SqlValueNode public CountNode(SelectNode subSelect) { - ArgumentGuard.NotNull(subSelect); + ArgumentNullException.ThrowIfNull(subSelect); SubSelect = subSelect; } diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/CountSelectorNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/CountSelectorNode.cs index d0b9e18ca2..d344659393 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/CountSelectorNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/CountSelectorNode.cs @@ -8,7 +8,8 @@ namespace DapperExample.TranslationToSql.TreeNodes; /// SELECT COUNT(*) FROM Users /// ]]>. /// -internal sealed class CountSelectorNode(string? alias) : SelectorNode(alias) +internal sealed class CountSelectorNode(string? alias) + : SelectorNode(alias) { public override TResult Accept(SqlTreeNodeVisitor visitor, TArgument argument) { diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/DeleteNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/DeleteNode.cs index aa3968f872..512e0e7321 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/DeleteNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/DeleteNode.cs @@ -1,5 +1,3 @@ -using JsonApiDotNetCore; - namespace DapperExample.TranslationToSql.TreeNodes; /// @@ -14,8 +12,8 @@ internal sealed class DeleteNode : SqlTreeNode public DeleteNode(TableNode table, WhereNode where) { - ArgumentGuard.NotNull(table); - ArgumentGuard.NotNull(where); + ArgumentNullException.ThrowIfNull(table); + ArgumentNullException.ThrowIfNull(where); Table = table; Where = where; diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/ExistsNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/ExistsNode.cs index b73882122c..96087886f9 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/ExistsNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/ExistsNode.cs @@ -1,5 +1,3 @@ -using JsonApiDotNetCore; - namespace DapperExample.TranslationToSql.TreeNodes; /// @@ -16,7 +14,7 @@ internal sealed class ExistsNode : FilterNode public ExistsNode(SelectNode subSelect) { - ArgumentGuard.NotNull(subSelect); + ArgumentNullException.ThrowIfNull(subSelect); SubSelect = subSelect; } diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/FromNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/FromNode.cs index 3d29636212..9e39a9d516 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/FromNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/FromNode.cs @@ -5,7 +5,8 @@ namespace DapperExample.TranslationToSql.TreeNodes; /// FROM Customers AS t1 /// ]]>. /// -internal sealed class FromNode(TableSourceNode source) : TableAccessorNode(source) +internal sealed class FromNode(TableSourceNode source) + : TableAccessorNode(source) { public override TResult Accept(SqlTreeNodeVisitor visitor, TArgument argument) { diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/InNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/InNode.cs index 26d3c2ec47..114a141eaa 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/InNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/InNode.cs @@ -14,7 +14,7 @@ internal sealed class InNode : FilterNode public InNode(ColumnNode column, IReadOnlyList values) { - ArgumentGuard.NotNull(column); + ArgumentNullException.ThrowIfNull(column); ArgumentGuard.NotNullNorEmpty(values); Column = column; diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/InsertNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/InsertNode.cs index 8ed6770136..f85857f677 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/InsertNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/InsertNode.cs @@ -14,7 +14,7 @@ internal sealed class InsertNode : SqlTreeNode public InsertNode(TableNode table, IReadOnlyCollection assignments) { - ArgumentGuard.NotNull(table); + ArgumentNullException.ThrowIfNull(table); ArgumentGuard.NotNullNorEmpty(assignments); Table = table; diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/JoinNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/JoinNode.cs index 6ed2e4c73c..48140a0c04 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/JoinNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/JoinNode.cs @@ -1,5 +1,3 @@ -using JsonApiDotNetCore; - namespace DapperExample.TranslationToSql.TreeNodes; /// @@ -16,8 +14,8 @@ internal sealed class JoinNode : TableAccessorNode public JoinNode(JoinType joinType, TableSourceNode source, ColumnNode outerColumn, ColumnNode innerColumn) : base(source) { - ArgumentGuard.NotNull(outerColumn); - ArgumentGuard.NotNull(innerColumn); + ArgumentNullException.ThrowIfNull(outerColumn); + ArgumentNullException.ThrowIfNull(innerColumn); JoinType = joinType; OuterColumn = outerColumn; diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/LikeNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/LikeNode.cs index 034e5c012e..f713e687fc 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/LikeNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/LikeNode.cs @@ -1,4 +1,3 @@ -using JsonApiDotNetCore; using JsonApiDotNetCore.Queries.Expressions; namespace DapperExample.TranslationToSql.TreeNodes; @@ -16,8 +15,8 @@ internal sealed class LikeNode : FilterNode public LikeNode(ColumnNode column, TextMatchKind matchKind, string text) { - ArgumentGuard.NotNull(column); - ArgumentGuard.NotNull(text); + ArgumentNullException.ThrowIfNull(column); + ArgumentNullException.ThrowIfNull(text); Column = column; MatchKind = matchKind; diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/LogicalNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/LogicalNode.cs index 40fc95b88c..ebf0554167 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/LogicalNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/LogicalNode.cs @@ -1,4 +1,3 @@ -using JsonApiDotNetCore; using JsonApiDotNetCore.Queries.Expressions; namespace DapperExample.TranslationToSql.TreeNodes; @@ -14,13 +13,13 @@ internal sealed class LogicalNode : FilterNode public IReadOnlyList Terms { get; } public LogicalNode(LogicalOperator @operator, params FilterNode[] terms) - : this(@operator, terms.ToList()) + : this(@operator, terms.AsReadOnly()) { } public LogicalNode(LogicalOperator @operator, IReadOnlyList terms) { - ArgumentGuard.NotNull(terms); + ArgumentNullException.ThrowIfNull(terms); if (terms.Count < 2) { diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/NotNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/NotNode.cs index 38c5d80f26..f1f2e9ed22 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/NotNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/NotNode.cs @@ -1,5 +1,3 @@ -using JsonApiDotNetCore; - namespace DapperExample.TranslationToSql.TreeNodes; /// @@ -13,7 +11,7 @@ internal sealed class NotNode : FilterNode public NotNode(FilterNode child) { - ArgumentGuard.NotNull(child); + ArgumentNullException.ThrowIfNull(child); Child = child; } diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/OneSelectorNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/OneSelectorNode.cs index a9c05301a7..ac9e75d44d 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/OneSelectorNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/OneSelectorNode.cs @@ -8,7 +8,8 @@ namespace DapperExample.TranslationToSql.TreeNodes; /// SELECT 1 FROM Users /// ]]>. /// -internal sealed class OneSelectorNode(string? alias) : SelectorNode(alias) +internal sealed class OneSelectorNode(string? alias) + : SelectorNode(alias) { public override TResult Accept(SqlTreeNodeVisitor visitor, TArgument argument) { diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/OrderByColumnNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/OrderByColumnNode.cs index 372b1e86ff..a62094ae5b 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/OrderByColumnNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/OrderByColumnNode.cs @@ -1,5 +1,3 @@ -using JsonApiDotNetCore; - namespace DapperExample.TranslationToSql.TreeNodes; /// @@ -17,7 +15,7 @@ internal sealed class OrderByColumnNode : OrderByTermNode public OrderByColumnNode(ColumnNode column, bool isAscending) : base(isAscending) { - ArgumentGuard.NotNull(column); + ArgumentNullException.ThrowIfNull(column); Column = column; } diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/OrderByCountNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/OrderByCountNode.cs index 3d8f8c240a..c044d98ba9 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/OrderByCountNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/OrderByCountNode.cs @@ -1,5 +1,3 @@ -using JsonApiDotNetCore; - namespace DapperExample.TranslationToSql.TreeNodes; /// @@ -17,7 +15,7 @@ internal sealed class OrderByCountNode : OrderByTermNode public OrderByCountNode(CountNode count, bool isAscending) : base(isAscending) { - ArgumentGuard.NotNull(count); + ArgumentNullException.ThrowIfNull(count); Count = count; } diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/ParameterNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/ParameterNode.cs index c2a5824f72..6e206fa04d 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/ParameterNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/ParameterNode.cs @@ -1,5 +1,3 @@ -using JsonApiDotNetCore; - namespace DapperExample.TranslationToSql.TreeNodes; /// @@ -16,7 +14,7 @@ internal sealed class ParameterNode : SqlValueNode public ParameterNode(string name, object? value) { - ArgumentGuard.NotNull(name); + ArgumentException.ThrowIfNullOrEmpty(name); if (!name.StartsWith('@') || name.Length < 2) { diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/SelectNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/SelectNode.cs index 0fc42b1ba0..add1ddc433 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/SelectNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/SelectNode.cs @@ -19,7 +19,7 @@ internal sealed class SelectNode : TableSourceNode public WhereNode? Where { get; } public OrderByNode? OrderBy { get; } - public override IReadOnlyList Columns => _columns; + public override IReadOnlyList Columns => _columns.AsReadOnly(); public SelectNode(IReadOnlyDictionary> selectors, WhereNode? where, OrderByNode? orderBy, string? alias) : base(alias) diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/TableAccessorNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/TableAccessorNode.cs index 4096789919..2822749230 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/TableAccessorNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/TableAccessorNode.cs @@ -1,5 +1,3 @@ -using JsonApiDotNetCore; - namespace DapperExample.TranslationToSql.TreeNodes; /// @@ -11,7 +9,7 @@ internal abstract class TableAccessorNode : SqlTreeNode protected TableAccessorNode(TableSourceNode source) { - ArgumentGuard.NotNull(source); + ArgumentNullException.ThrowIfNull(source); Source = source; } diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/TableNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/TableNode.cs index 31977f1546..9fca1971cb 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/TableNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/TableNode.cs @@ -1,5 +1,4 @@ using Humanizer; -using JsonApiDotNetCore; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Resources.Annotations; @@ -21,13 +20,13 @@ internal sealed class TableNode : TableSourceNode public string Name => _resourceType.ClrType.Name.Pluralize(); - public override IReadOnlyList Columns => _columns; + public override IReadOnlyList Columns => _columns.AsReadOnly(); public TableNode(ResourceType resourceType, IReadOnlyDictionary columnMappings, string? alias) : base(alias) { - ArgumentGuard.NotNull(resourceType); - ArgumentGuard.NotNull(columnMappings); + ArgumentNullException.ThrowIfNull(resourceType); + ArgumentNullException.ThrowIfNull(columnMappings); _resourceType = resourceType; _columnMappings = columnMappings; diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/UpdateNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/UpdateNode.cs index 3aa5dbdf73..7f9b1b79a4 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/UpdateNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/UpdateNode.cs @@ -15,9 +15,9 @@ internal sealed class UpdateNode : SqlTreeNode public UpdateNode(TableNode table, IReadOnlyCollection assignments, WhereNode where) { - ArgumentGuard.NotNull(table); + ArgumentNullException.ThrowIfNull(table); ArgumentGuard.NotNullNorEmpty(assignments); - ArgumentGuard.NotNull(where); + ArgumentNullException.ThrowIfNull(where); Table = table; Assignments = assignments; diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/WhereNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/WhereNode.cs index d8d72601c5..4e8c4d54e8 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/WhereNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/WhereNode.cs @@ -1,5 +1,3 @@ -using JsonApiDotNetCore; - namespace DapperExample.TranslationToSql.TreeNodes; /// @@ -13,7 +11,7 @@ internal sealed class WhereNode : SqlTreeNode public WhereNode(FilterNode filter) { - ArgumentGuard.NotNull(filter); + ArgumentNullException.ThrowIfNull(filter); Filter = filter; } diff --git a/src/Examples/DatabasePerTenantExample/DatabasePerTenantExample.csproj b/src/Examples/DatabasePerTenantExample/DatabasePerTenantExample.csproj index 0ccb4bbc5f..3edc993428 100644 --- a/src/Examples/DatabasePerTenantExample/DatabasePerTenantExample.csproj +++ b/src/Examples/DatabasePerTenantExample/DatabasePerTenantExample.csproj @@ -1,6 +1,6 @@ - net8.0;net6.0 + net9.0;net8.0 diff --git a/src/Examples/DatabasePerTenantExample/Program.cs b/src/Examples/DatabasePerTenantExample/Program.cs index 1414e28424..4b88357d78 100644 --- a/src/Examples/DatabasePerTenantExample/Program.cs +++ b/src/Examples/DatabasePerTenantExample/Program.cs @@ -38,7 +38,7 @@ await CreateDatabaseAsync("AdventureWorks", app.Services); await CreateDatabaseAsync("Contoso", app.Services); -app.Run(); +await app.RunAsync(); [Conditional("DEBUG")] static void SetDbContextDebugOptions(DbContextOptionsBuilder options) diff --git a/src/Examples/GettingStarted/Data/SampleDbContext.cs b/src/Examples/GettingStarted/Data/SampleDbContext.cs index 5e65f8466e..cd8b16515d 100644 --- a/src/Examples/GettingStarted/Data/SampleDbContext.cs +++ b/src/Examples/GettingStarted/Data/SampleDbContext.cs @@ -5,7 +5,8 @@ namespace GettingStarted.Data; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public class SampleDbContext(DbContextOptions options) : DbContext(options) +public class SampleDbContext(DbContextOptions options) + : DbContext(options) { public DbSet Books => Set(); } diff --git a/src/Examples/GettingStarted/GettingStarted.csproj b/src/Examples/GettingStarted/GettingStarted.csproj index 1f4645f323..611aeb37a5 100644 --- a/src/Examples/GettingStarted/GettingStarted.csproj +++ b/src/Examples/GettingStarted/GettingStarted.csproj @@ -1,6 +1,6 @@ - net8.0;net6.0 + net9.0;net8.0 diff --git a/src/Examples/GettingStarted/Program.cs b/src/Examples/GettingStarted/Program.cs index 9ce6beda08..634e130a3f 100644 --- a/src/Examples/GettingStarted/Program.cs +++ b/src/Examples/GettingStarted/Program.cs @@ -38,7 +38,7 @@ await CreateDatabaseAsync(app.Services); -app.Run(); +await app.RunAsync(); [Conditional("DEBUG")] static void SetDbContextDebugOptions(DbContextOptionsBuilder options) diff --git a/src/Examples/GettingStarted/README.md b/src/Examples/GettingStarted/README.md index 563899a827..8d8da60bc8 100644 --- a/src/Examples/GettingStarted/README.md +++ b/src/Examples/GettingStarted/README.md @@ -11,4 +11,4 @@ For further documentation and implementation of a JsonApiDotNetCore Application Repository: https://github.com/json-api-dotnet/JsonApiDotNetCore -Documentation: http://www.jsonapi.net +Documentation: https://www.jsonapi.net diff --git a/src/Examples/JsonApiDotNetCoreExample/AppLog.cs b/src/Examples/JsonApiDotNetCoreExample/AppLog.cs new file mode 100644 index 0000000000..6cb4af1a55 --- /dev/null +++ b/src/Examples/JsonApiDotNetCoreExample/AppLog.cs @@ -0,0 +1,9 @@ +#pragma warning disable AV1008 // Class should not be static + +namespace JsonApiDotNetCoreExample; + +internal static partial class AppLog +{ + [LoggerMessage(Level = LogLevel.Information, SkipEnabledCheck = true, Message = "Measurement results for application startup:{LineBreak}{TimingResults}")] + public static partial void LogStartupTimings(ILogger logger, string lineBreak, string timingResults); +} diff --git a/src/Examples/JsonApiDotNetCoreExample/Controllers/NonJsonApiController.cs b/src/Examples/JsonApiDotNetCoreExample/Controllers/NonJsonApiController.cs index 3c89ac3bcf..aa51110869 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Controllers/NonJsonApiController.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Controllers/NonJsonApiController.cs @@ -16,7 +16,8 @@ public IActionResult Get() [HttpPost] public async Task PostAsync() { - string name = await new StreamReader(Request.Body).ReadToEndAsync(); + using var reader = new StreamReader(Request.Body, leaveOpen: true); + string name = await reader.ReadToEndAsync(); if (string.IsNullOrEmpty(name)) { diff --git a/src/Examples/JsonApiDotNetCoreExample/Controllers/OperationsController.cs b/src/Examples/JsonApiDotNetCoreExample/Controllers/OperationsController.cs index 9d8d944967..a5cb2ef2e3 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Controllers/OperationsController.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Controllers/OperationsController.cs @@ -8,5 +8,5 @@ namespace JsonApiDotNetCoreExample.Controllers; public sealed class OperationsController( IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, IOperationsProcessor processor, IJsonApiRequest request, - ITargetedFields targetedFields, IAtomicOperationFilter operationFilter) : JsonApiOperationsController(options, resourceGraph, loggerFactory, processor, - request, targetedFields, operationFilter); + ITargetedFields targetedFields, IAtomicOperationFilter operationFilter) + : JsonApiOperationsController(options, resourceGraph, loggerFactory, processor, request, targetedFields, operationFilter); diff --git a/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs b/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs index e7864a42f6..f5c7e8e401 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs @@ -8,7 +8,8 @@ namespace JsonApiDotNetCoreExample.Data; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class AppDbContext(DbContextOptions options) : DbContext(options) +public sealed class AppDbContext(DbContextOptions options) + : DbContext(options) { public DbSet TodoItems => Set(); diff --git a/src/Examples/JsonApiDotNetCoreExample/Definitions/TodoItemDefinition.cs b/src/Examples/JsonApiDotNetCoreExample/Definitions/TodoItemDefinition.cs index d94fffa85b..06036968d0 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Definitions/TodoItemDefinition.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Definitions/TodoItemDefinition.cs @@ -5,27 +5,14 @@ using JsonApiDotNetCore.Queries.Expressions; using JsonApiDotNetCore.Resources; using JsonApiDotNetCoreExample.Models; -#if NET6_0 -using Microsoft.AspNetCore.Authentication; -#endif namespace JsonApiDotNetCoreExample.Definitions; [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] -public sealed class TodoItemDefinition( - IResourceGraph resourceGraph, -#if NET6_0 - ISystemClock systemClock -#else - TimeProvider timeProvider -#endif -) : JsonApiResourceDefinition(resourceGraph) +public sealed class TodoItemDefinition(IResourceGraph resourceGraph, TimeProvider timeProvider) + : JsonApiResourceDefinition(resourceGraph) { -#if NET6_0 - private readonly Func _getUtcNow = () => systemClock.UtcNow; -#else - private readonly Func _getUtcNow = timeProvider.GetUtcNow; -#endif + private readonly TimeProvider _timeProvider = timeProvider; public override SortExpression OnApplySort(SortExpression? existingSort) { @@ -44,11 +31,11 @@ public override Task OnWritingAsync(TodoItem resource, WriteOperationKind writeO { if (writeOperation == WriteOperationKind.CreateResource) { - resource.CreatedAt = _getUtcNow(); + resource.CreatedAt = _timeProvider.GetUtcNow(); } else if (writeOperation == WriteOperationKind.UpdateResource) { - resource.LastModifiedAt = _getUtcNow(); + resource.LastModifiedAt = _timeProvider.GetUtcNow(); } return Task.CompletedTask; diff --git a/src/Examples/JsonApiDotNetCoreExample/GeneratedSwagger/JsonApiDotNetCoreExample.json b/src/Examples/JsonApiDotNetCoreExample/GeneratedSwagger/JsonApiDotNetCoreExample.json new file mode 100644 index 0000000000..4863000598 --- /dev/null +++ b/src/Examples/JsonApiDotNetCoreExample/GeneratedSwagger/JsonApiDotNetCoreExample.json @@ -0,0 +1,8583 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "JsonApiDotNetCoreExample", + "version": "1.0" + }, + "servers": [ + { + "url": "https://localhost:44340" + } + ], + "paths": { + "/api/operations": { + "post": { + "tags": [ + "operations" + ], + "summary": "Performs multiple mutations in a linear and atomic manner.", + "operationId": "postOperations", + "requestBody": { + "description": "An array of mutation operations. For syntax, see the [Atomic Operations documentation](https://jsonapi.org/ext/atomic/).", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/operationsRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "All operations were successfully applied, which resulted in additional changes.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/operationsResponseDocument" + } + } + } + }, + "204": { + "description": "All operations were successfully applied, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "An operation is not accessible or a client-generated ID is used.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/api/people": { + "get": { + "tags": [ + "people" + ], + "summary": "Retrieves a collection of people.", + "operationId": "getPersonCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found people, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/personCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "people" + ], + "summary": "Retrieves a collection of people without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headPersonCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "people" + ], + "summary": "Creates a new person.", + "operationId": "postPerson", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the person to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createPersonRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The person was successfully created, which resulted in additional changes. The newly created person is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created person can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryPersonResponseDocument" + } + } + } + }, + "204": { + "description": "The person was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/api/people/{id}": { + "get": { + "tags": [ + "people" + ], + "summary": "Retrieves an individual person by its identifier.", + "operationId": "getPerson", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the person to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found person.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryPersonResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The person does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "people" + ], + "summary": "Retrieves an individual person by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headPerson", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the person to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The person does not exist." + } + } + }, + "patch": { + "tags": [ + "people" + ], + "summary": "Updates an existing person.", + "operationId": "patchPerson", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the person to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the person to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updatePersonRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The person was successfully updated, which resulted in additional changes. The updated person is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryPersonResponseDocument" + } + } + } + }, + "204": { + "description": "The person was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The person or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "people" + ], + "summary": "Deletes an existing person by its identifier.", + "operationId": "deletePerson", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the person to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "The person was successfully deleted." + }, + "404": { + "description": "The person does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/api/people/{id}/assignedTodoItems": { + "get": { + "tags": [ + "people" + ], + "summary": "Retrieves the related todoItems of an individual person's assignedTodoItems relationship.", + "operationId": "getPersonAssignedTodoItems", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the person whose related todoItems to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found todoItems, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/todoItemCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The person does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "people" + ], + "summary": "Retrieves the related todoItems of an individual person's assignedTodoItems relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headPersonAssignedTodoItems", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the person whose related todoItems to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The person does not exist." + } + } + } + }, + "/api/people/{id}/relationships/assignedTodoItems": { + "get": { + "tags": [ + "people" + ], + "summary": "Retrieves the related todoItem identities of an individual person's assignedTodoItems relationship.", + "operationId": "getPersonAssignedTodoItemsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the person whose related todoItem identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found todoItem identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/todoItemIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The person does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "people" + ], + "summary": "Retrieves the related todoItem identities of an individual person's assignedTodoItems relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headPersonAssignedTodoItemsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the person whose related todoItem identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The person does not exist." + } + } + }, + "post": { + "tags": [ + "people" + ], + "summary": "Adds existing todoItems to the assignedTodoItems relationship of an individual person.", + "operationId": "postPersonAssignedTodoItemsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the person to add todoItems to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the todoItems to add to the assignedTodoItems relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTodoItemInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The todoItems were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The person or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "people" + ], + "summary": "Assigns existing todoItems to the assignedTodoItems relationship of an individual person.", + "operationId": "patchPersonAssignedTodoItemsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the person whose assignedTodoItems relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the todoItems to assign to the assignedTodoItems relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTodoItemInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The assignedTodoItems relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The person or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "people" + ], + "summary": "Removes existing todoItems from the assignedTodoItems relationship of an individual person.", + "operationId": "deletePersonAssignedTodoItemsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the person to remove todoItems from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the todoItems to remove from the assignedTodoItems relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTodoItemInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The todoItems were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The person or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/api/people/{id}/ownedTodoItems": { + "get": { + "tags": [ + "people" + ], + "summary": "Retrieves the related todoItems of an individual person's ownedTodoItems relationship.", + "operationId": "getPersonOwnedTodoItems", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the person whose related todoItems to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found todoItems, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/todoItemCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The person does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "people" + ], + "summary": "Retrieves the related todoItems of an individual person's ownedTodoItems relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headPersonOwnedTodoItems", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the person whose related todoItems to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The person does not exist." + } + } + } + }, + "/api/people/{id}/relationships/ownedTodoItems": { + "get": { + "tags": [ + "people" + ], + "summary": "Retrieves the related todoItem identities of an individual person's ownedTodoItems relationship.", + "operationId": "getPersonOwnedTodoItemsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the person whose related todoItem identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found todoItem identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/todoItemIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The person does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "people" + ], + "summary": "Retrieves the related todoItem identities of an individual person's ownedTodoItems relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headPersonOwnedTodoItemsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the person whose related todoItem identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The person does not exist." + } + } + }, + "post": { + "tags": [ + "people" + ], + "summary": "Adds existing todoItems to the ownedTodoItems relationship of an individual person.", + "operationId": "postPersonOwnedTodoItemsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the person to add todoItems to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the todoItems to add to the ownedTodoItems relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTodoItemInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The todoItems were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The person or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "people" + ], + "summary": "Assigns existing todoItems to the ownedTodoItems relationship of an individual person.", + "operationId": "patchPersonOwnedTodoItemsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the person whose ownedTodoItems relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the todoItems to assign to the ownedTodoItems relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTodoItemInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The ownedTodoItems relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The person or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "people" + ], + "summary": "Removes existing todoItems from the ownedTodoItems relationship of an individual person.", + "operationId": "deletePersonOwnedTodoItemsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the person to remove todoItems from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the todoItems to remove from the ownedTodoItems relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTodoItemInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The todoItems were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The person or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/api/tags": { + "get": { + "tags": [ + "tags" + ], + "summary": "Retrieves a collection of tags.", + "operationId": "getTagCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found tags, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/tagCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "tags" + ], + "summary": "Retrieves a collection of tags without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headTagCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "tags" + ], + "summary": "Creates a new tag.", + "operationId": "postTag", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the tag to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createTagRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The tag was successfully created, which resulted in additional changes. The newly created tag is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created tag can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryTagResponseDocument" + } + } + } + }, + "204": { + "description": "The tag was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/api/tags/{id}": { + "get": { + "tags": [ + "tags" + ], + "summary": "Retrieves an individual tag by its identifier.", + "operationId": "getTag", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the tag to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found tag.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryTagResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The tag does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "tags" + ], + "summary": "Retrieves an individual tag by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headTag", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the tag to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The tag does not exist." + } + } + }, + "patch": { + "tags": [ + "tags" + ], + "summary": "Updates an existing tag.", + "operationId": "patchTag", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the tag to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the tag to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateTagRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The tag was successfully updated, which resulted in additional changes. The updated tag is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryTagResponseDocument" + } + } + } + }, + "204": { + "description": "The tag was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The tag or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "tags" + ], + "summary": "Deletes an existing tag by its identifier.", + "operationId": "deleteTag", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the tag to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "The tag was successfully deleted." + }, + "404": { + "description": "The tag does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/api/tags/{id}/todoItems": { + "get": { + "tags": [ + "tags" + ], + "summary": "Retrieves the related todoItems of an individual tag's todoItems relationship.", + "operationId": "getTagTodoItems", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the tag whose related todoItems to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found todoItems, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/todoItemCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The tag does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "tags" + ], + "summary": "Retrieves the related todoItems of an individual tag's todoItems relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headTagTodoItems", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the tag whose related todoItems to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The tag does not exist." + } + } + } + }, + "/api/tags/{id}/relationships/todoItems": { + "get": { + "tags": [ + "tags" + ], + "summary": "Retrieves the related todoItem identities of an individual tag's todoItems relationship.", + "operationId": "getTagTodoItemsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the tag whose related todoItem identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found todoItem identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/todoItemIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The tag does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "tags" + ], + "summary": "Retrieves the related todoItem identities of an individual tag's todoItems relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headTagTodoItemsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the tag whose related todoItem identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The tag does not exist." + } + } + }, + "post": { + "tags": [ + "tags" + ], + "summary": "Adds existing todoItems to the todoItems relationship of an individual tag.", + "operationId": "postTagTodoItemsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the tag to add todoItems to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the todoItems to add to the todoItems relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTodoItemInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The todoItems were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The tag or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "tags" + ], + "summary": "Assigns existing todoItems to the todoItems relationship of an individual tag.", + "operationId": "patchTagTodoItemsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the tag whose todoItems relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the todoItems to assign to the todoItems relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTodoItemInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The todoItems relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The tag or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "tags" + ], + "summary": "Removes existing todoItems from the todoItems relationship of an individual tag.", + "operationId": "deleteTagTodoItemsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the tag to remove todoItems from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the todoItems to remove from the todoItems relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTodoItemInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The todoItems were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The tag or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/api/todoItems": { + "get": { + "tags": [ + "todoItems" + ], + "summary": "Retrieves a collection of todoItems.", + "operationId": "getTodoItemCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found todoItems, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/todoItemCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "todoItems" + ], + "summary": "Retrieves a collection of todoItems without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headTodoItemCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "todoItems" + ], + "summary": "Creates a new todoItem.", + "operationId": "postTodoItem", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the todoItem to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createTodoItemRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The todoItem was successfully created, which resulted in additional changes. The newly created todoItem is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created todoItem can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryTodoItemResponseDocument" + } + } + } + }, + "204": { + "description": "The todoItem was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/api/todoItems/{id}": { + "get": { + "tags": [ + "todoItems" + ], + "summary": "Retrieves an individual todoItem by its identifier.", + "operationId": "getTodoItem", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the todoItem to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found todoItem.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryTodoItemResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The todoItem does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "todoItems" + ], + "summary": "Retrieves an individual todoItem by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headTodoItem", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the todoItem to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The todoItem does not exist." + } + } + }, + "patch": { + "tags": [ + "todoItems" + ], + "summary": "Updates an existing todoItem.", + "operationId": "patchTodoItem", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the todoItem to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the todoItem to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateTodoItemRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The todoItem was successfully updated, which resulted in additional changes. The updated todoItem is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryTodoItemResponseDocument" + } + } + } + }, + "204": { + "description": "The todoItem was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The todoItem or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "todoItems" + ], + "summary": "Deletes an existing todoItem by its identifier.", + "operationId": "deleteTodoItem", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the todoItem to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "The todoItem was successfully deleted." + }, + "404": { + "description": "The todoItem does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/api/todoItems/{id}/assignee": { + "get": { + "tags": [ + "todoItems" + ], + "summary": "Retrieves the related person of an individual todoItem's assignee relationship.", + "operationId": "getTodoItemAssignee", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the todoItem whose related person to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found person, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullableSecondaryPersonResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The todoItem does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "todoItems" + ], + "summary": "Retrieves the related person of an individual todoItem's assignee relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headTodoItemAssignee", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the todoItem whose related person to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The todoItem does not exist." + } + } + } + }, + "/api/todoItems/{id}/relationships/assignee": { + "get": { + "tags": [ + "todoItems" + ], + "summary": "Retrieves the related person identity of an individual todoItem's assignee relationship.", + "operationId": "getTodoItemAssigneeRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the todoItem whose related person identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found person identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullablePersonIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The todoItem does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "todoItems" + ], + "summary": "Retrieves the related person identity of an individual todoItem's assignee relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headTodoItemAssigneeRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the todoItem whose related person identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The todoItem does not exist." + } + } + }, + "patch": { + "tags": [ + "todoItems" + ], + "summary": "Clears or assigns an existing person to the assignee relationship of an individual todoItem.", + "operationId": "patchTodoItemAssigneeRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the todoItem whose assignee relationship to assign or clear.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identity of the person to assign to the assignee relationship, or `null` to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOnePersonInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The assignee relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The todoItem or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/api/todoItems/{id}/owner": { + "get": { + "tags": [ + "todoItems" + ], + "summary": "Retrieves the related person of an individual todoItem's owner relationship.", + "operationId": "getTodoItemOwner", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the todoItem whose related person to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found person, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/secondaryPersonResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The todoItem does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "todoItems" + ], + "summary": "Retrieves the related person of an individual todoItem's owner relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headTodoItemOwner", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the todoItem whose related person to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The todoItem does not exist." + } + } + } + }, + "/api/todoItems/{id}/relationships/owner": { + "get": { + "tags": [ + "todoItems" + ], + "summary": "Retrieves the related person identity of an individual todoItem's owner relationship.", + "operationId": "getTodoItemOwnerRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the todoItem whose related person identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found person identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/personIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The todoItem does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "todoItems" + ], + "summary": "Retrieves the related person identity of an individual todoItem's owner relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headTodoItemOwnerRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the todoItem whose related person identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The todoItem does not exist." + } + } + }, + "patch": { + "tags": [ + "todoItems" + ], + "summary": "Assigns an existing person to the owner relationship of an individual todoItem.", + "operationId": "patchTodoItemOwnerRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the todoItem whose owner relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identity of the person to assign to the owner relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOnePersonInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The owner relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The todoItem or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/api/todoItems/{id}/tags": { + "get": { + "tags": [ + "todoItems" + ], + "summary": "Retrieves the related tags of an individual todoItem's tags relationship.", + "operationId": "getTodoItemTags", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the todoItem whose related tags to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found tags, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/tagCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The todoItem does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "todoItems" + ], + "summary": "Retrieves the related tags of an individual todoItem's tags relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headTodoItemTags", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the todoItem whose related tags to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The todoItem does not exist." + } + } + } + }, + "/api/todoItems/{id}/relationships/tags": { + "get": { + "tags": [ + "todoItems" + ], + "summary": "Retrieves the related tag identities of an individual todoItem's tags relationship.", + "operationId": "getTodoItemTagsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the todoItem whose related tag identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found tag identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/tagIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The todoItem does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "todoItems" + ], + "summary": "Retrieves the related tag identities of an individual todoItem's tags relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headTodoItemTagsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the todoItem whose related tag identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The todoItem does not exist." + } + } + }, + "post": { + "tags": [ + "todoItems" + ], + "summary": "Adds existing tags to the tags relationship of an individual todoItem.", + "operationId": "postTodoItemTagsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the todoItem to add tags to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the tags to add to the tags relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTagInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The tags were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The todoItem or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "todoItems" + ], + "summary": "Assigns existing tags to the tags relationship of an individual todoItem.", + "operationId": "patchTodoItemTagsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the todoItem whose tags relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the tags to assign to the tags relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTagInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The tags relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The todoItem or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "todoItems" + ], + "summary": "Removes existing tags from the tags relationship of an individual todoItem.", + "operationId": "deleteTodoItemTagsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the todoItem to remove tags from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the tags to remove from the tags relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTagInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The tags were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The todoItem or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "addOperationCode": { + "enum": [ + "add" + ], + "type": "string" + }, + "addToPersonAssignedTodoItemsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/personAssignedTodoItemsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/todoItemIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "addToPersonOwnedTodoItemsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/personOwnedTodoItemsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/todoItemIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "addToTagTodoItemsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/tagTodoItemsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/todoItemIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "addToTodoItemTagsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/todoItemTagsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/tagIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "atomicOperation": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "type": "string" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "addPerson": "#/components/schemas/createPersonOperation", + "addTag": "#/components/schemas/createTagOperation", + "addToPersonAssignedTodoItems": "#/components/schemas/addToPersonAssignedTodoItemsRelationshipOperation", + "addToPersonOwnedTodoItems": "#/components/schemas/addToPersonOwnedTodoItemsRelationshipOperation", + "addToTagTodoItems": "#/components/schemas/addToTagTodoItemsRelationshipOperation", + "addToTodoItemTags": "#/components/schemas/addToTodoItemTagsRelationshipOperation", + "addTodoItem": "#/components/schemas/createTodoItemOperation", + "removeFromPersonAssignedTodoItems": "#/components/schemas/removeFromPersonAssignedTodoItemsRelationshipOperation", + "removeFromPersonOwnedTodoItems": "#/components/schemas/removeFromPersonOwnedTodoItemsRelationshipOperation", + "removeFromTagTodoItems": "#/components/schemas/removeFromTagTodoItemsRelationshipOperation", + "removeFromTodoItemTags": "#/components/schemas/removeFromTodoItemTagsRelationshipOperation", + "removePerson": "#/components/schemas/deletePersonOperation", + "removeTag": "#/components/schemas/deleteTagOperation", + "removeTodoItem": "#/components/schemas/deleteTodoItemOperation", + "updatePerson": "#/components/schemas/updatePersonOperation", + "updatePersonAssignedTodoItems": "#/components/schemas/updatePersonAssignedTodoItemsRelationshipOperation", + "updatePersonOwnedTodoItems": "#/components/schemas/updatePersonOwnedTodoItemsRelationshipOperation", + "updateTag": "#/components/schemas/updateTagOperation", + "updateTagTodoItems": "#/components/schemas/updateTagTodoItemsRelationshipOperation", + "updateTodoItem": "#/components/schemas/updateTodoItemOperation", + "updateTodoItemAssignee": "#/components/schemas/updateTodoItemAssigneeRelationshipOperation", + "updateTodoItemOwner": "#/components/schemas/updateTodoItemOwnerRelationshipOperation", + "updateTodoItemTags": "#/components/schemas/updateTodoItemTagsRelationshipOperation" + } + }, + "x-abstract": true + }, + "atomicResult": { + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "attributesInCreatePersonRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "lastName" + ], + "type": "object", + "properties": { + "firstName": { + "type": "string", + "nullable": true + }, + "lastName": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "people": "#/components/schemas/attributesInCreatePersonRequest", + "tags": "#/components/schemas/attributesInCreateTagRequest", + "todoItems": "#/components/schemas/attributesInCreateTodoItemRequest" + } + }, + "x-abstract": true + }, + "attributesInCreateTagRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateTodoItemRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "description", + "priority" + ], + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "priority": { + "allOf": [ + { + "$ref": "#/components/schemas/todoItemPriority" + } + ] + }, + "durationInHours": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInPersonResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "firstName": { + "type": "string", + "nullable": true + }, + "lastName": { + "type": "string" + }, + "displayName": { + "type": "string", + "readOnly": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "people": "#/components/schemas/attributesInPersonResponse", + "tags": "#/components/schemas/attributesInTagResponse", + "todoItems": "#/components/schemas/attributesInTodoItemResponse" + } + }, + "x-abstract": true + }, + "attributesInTagResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "name": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInTodoItemResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "priority": { + "allOf": [ + { + "$ref": "#/components/schemas/todoItemPriority" + } + ] + }, + "durationInHours": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "modifiedAt": { + "type": "string", + "format": "date-time", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdatePersonRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "firstName": { + "type": "string", + "nullable": true + }, + "lastName": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "people": "#/components/schemas/attributesInUpdatePersonRequest", + "tags": "#/components/schemas/attributesInUpdateTagRequest", + "todoItems": "#/components/schemas/attributesInUpdateTodoItemRequest" + } + }, + "x-abstract": true + }, + "attributesInUpdateTagRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "name": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateTodoItemRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "priority": { + "allOf": [ + { + "$ref": "#/components/schemas/todoItemPriority" + } + ] + }, + "durationInHours": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createPersonOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreatePersonRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createPersonRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreatePersonRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "createTagOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateTagRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createTagRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateTagRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "createTodoItemOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateTodoItemRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createTodoItemRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateTodoItemRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "dataInCreatePersonRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreatePersonRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreatePersonRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateTagRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateTagRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateTagRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateTodoItemRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateTodoItemRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateTodoItemRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInPersonResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInPersonResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInPersonResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInTagResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInTagResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInTagResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInTodoItemResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInTodoItemResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInTodoItemResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdatePersonRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdatePersonRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdatePersonRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateTagRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateTagRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateTagRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateTodoItemRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateTodoItemRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateTodoItemRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "deletePersonOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/personIdentifierInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "deleteTagOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/tagIdentifierInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "deleteTodoItemOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/todoItemIdentifierInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "errorLinks": { + "type": "object", + "properties": { + "about": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorObject": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorLinks" + } + ], + "nullable": true + }, + "status": { + "type": "string" + }, + "code": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/errorSource" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorResponseDocument": { + "required": [ + "errors", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorTopLevelLinks" + } + ] + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/errorObject" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorSource": { + "type": "object", + "properties": { + "pointer": { + "type": "string", + "nullable": true + }, + "parameter": { + "type": "string", + "nullable": true + }, + "header": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "identifierInRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "people": "#/components/schemas/personIdentifierInRequest", + "tags": "#/components/schemas/tagIdentifierInRequest", + "todoItems": "#/components/schemas/todoItemIdentifierInRequest" + } + }, + "x-abstract": true + }, + "meta": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "nullablePersonIdentifierResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/personIdentifierInResponse" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableSecondaryPersonResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInPersonResponse" + } + ], + "nullable": true + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableToOnePersonInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/personIdentifierInRequest" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableToOnePersonInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/personIdentifierInResponse" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "operationsRequestDocument": { + "required": [ + "atomic:operations" + ], + "type": "object", + "properties": { + "atomic:operations": { + "minItems": 1, + "type": "array", + "items": { + "$ref": "#/components/schemas/atomicOperation" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "operationsResponseDocument": { + "required": [ + "atomic:results", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "atomic:results": { + "minItems": 1, + "type": "array", + "items": { + "$ref": "#/components/schemas/atomicResult" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "personAssignedTodoItemsRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/personResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/personAssignedTodoItemsRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "personAssignedTodoItemsRelationshipName": { + "enum": [ + "assignedTodoItems" + ], + "type": "string" + }, + "personCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInPersonResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "personIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "personIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/personResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "personIdentifierResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/personIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "personOwnedTodoItemsRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/personResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/personOwnedTodoItemsRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "personOwnedTodoItemsRelationshipName": { + "enum": [ + "ownedTodoItems" + ], + "type": "string" + }, + "personResourceType": { + "enum": [ + "people" + ], + "type": "string" + }, + "primaryPersonResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInPersonResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryTagResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInTagResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryTodoItemResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInTodoItemResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "relationshipLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + } + }, + "additionalProperties": false + }, + "relationshipsInCreatePersonRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "type": "object", + "properties": { + "ownedTodoItems": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTodoItemInRequest" + } + ] + }, + "assignedTodoItems": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTodoItemInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "people": "#/components/schemas/relationshipsInCreatePersonRequest", + "tags": "#/components/schemas/relationshipsInCreateTagRequest", + "todoItems": "#/components/schemas/relationshipsInCreateTodoItemRequest" + } + }, + "x-abstract": true + }, + "relationshipsInCreateTagRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "type": "object", + "properties": { + "todoItems": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTodoItemInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateTodoItemRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "required": [ + "owner" + ], + "type": "object", + "properties": { + "owner": { + "allOf": [ + { + "$ref": "#/components/schemas/toOnePersonInRequest" + } + ] + }, + "assignee": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOnePersonInRequest" + } + ] + }, + "tags": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTagInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInPersonResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "type": "object", + "properties": { + "ownedTodoItems": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTodoItemInResponse" + } + ] + }, + "assignedTodoItems": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTodoItemInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "people": "#/components/schemas/relationshipsInPersonResponse", + "tags": "#/components/schemas/relationshipsInTagResponse", + "todoItems": "#/components/schemas/relationshipsInTodoItemResponse" + } + }, + "x-abstract": true + }, + "relationshipsInTagResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "type": "object", + "properties": { + "todoItems": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTodoItemInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInTodoItemResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "type": "object", + "properties": { + "owner": { + "allOf": [ + { + "$ref": "#/components/schemas/toOnePersonInResponse" + } + ] + }, + "assignee": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOnePersonInResponse" + } + ] + }, + "tags": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTagInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdatePersonRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "ownedTodoItems": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTodoItemInRequest" + } + ] + }, + "assignedTodoItems": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTodoItemInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "people": "#/components/schemas/relationshipsInUpdatePersonRequest", + "tags": "#/components/schemas/relationshipsInUpdateTagRequest", + "todoItems": "#/components/schemas/relationshipsInUpdateTodoItemRequest" + } + }, + "x-abstract": true + }, + "relationshipsInUpdateTagRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "todoItems": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTodoItemInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateTodoItemRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "owner": { + "allOf": [ + { + "$ref": "#/components/schemas/toOnePersonInRequest" + } + ] + }, + "assignee": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOnePersonInRequest" + } + ] + }, + "tags": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTagInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "removeFromPersonAssignedTodoItemsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/personAssignedTodoItemsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/todoItemIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "removeFromPersonOwnedTodoItemsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/personOwnedTodoItemsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/todoItemIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "removeFromTagTodoItemsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/tagTodoItemsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/todoItemIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "removeFromTodoItemTagsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/todoItemTagsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/tagIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "removeOperationCode": { + "enum": [ + "remove" + ], + "type": "string" + }, + "resourceCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceIdentifierCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceIdentifierTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceInCreateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "people": "#/components/schemas/dataInCreatePersonRequest", + "tags": "#/components/schemas/dataInCreateTagRequest", + "todoItems": "#/components/schemas/dataInCreateTodoItemRequest" + } + }, + "x-abstract": true + }, + "resourceInResponse": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "people": "#/components/schemas/dataInPersonResponse", + "tags": "#/components/schemas/dataInTagResponse", + "todoItems": "#/components/schemas/dataInTodoItemResponse" + } + }, + "x-abstract": true + }, + "resourceInUpdateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "people": "#/components/schemas/dataInUpdatePersonRequest", + "tags": "#/components/schemas/dataInUpdateTagRequest", + "todoItems": "#/components/schemas/dataInUpdateTodoItemRequest" + } + }, + "x-abstract": true + }, + "resourceLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceType": { + "enum": [ + "people", + "tags", + "todoItems" + ], + "type": "string" + }, + "secondaryPersonResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInPersonResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "tagCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInTagResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "tagIdentifierCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/tagIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "tagIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "tagIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/tagResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "tagResourceType": { + "enum": [ + "tags" + ], + "type": "string" + }, + "tagTodoItemsRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/tagResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/tagTodoItemsRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "tagTodoItemsRelationshipName": { + "enum": [ + "todoItems" + ], + "type": "string" + }, + "toManyTagInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/tagIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyTagInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/tagIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyTodoItemInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/todoItemIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyTodoItemInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/todoItemIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOnePersonInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/personIdentifierInRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOnePersonInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/personIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "todoItemAssigneeRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/todoItemResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/todoItemAssigneeRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "todoItemAssigneeRelationshipName": { + "enum": [ + "assignee" + ], + "type": "string" + }, + "todoItemCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInTodoItemResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "todoItemIdentifierCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/todoItemIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "todoItemIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "todoItemIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/todoItemResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "todoItemOwnerRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/todoItemResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/todoItemOwnerRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "todoItemOwnerRelationshipName": { + "enum": [ + "owner" + ], + "type": "string" + }, + "todoItemPriority": { + "enum": [ + "High", + "Medium", + "Low" + ], + "type": "string" + }, + "todoItemResourceType": { + "enum": [ + "todoItems" + ], + "type": "string" + }, + "todoItemTagsRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/todoItemResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/todoItemTagsRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "todoItemTagsRelationshipName": { + "enum": [ + "tags" + ], + "type": "string" + }, + "updateOperationCode": { + "enum": [ + "update" + ], + "type": "string" + }, + "updatePersonAssignedTodoItemsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/personAssignedTodoItemsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/todoItemIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updatePersonOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/personIdentifierInRequest" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdatePersonRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updatePersonOwnedTodoItemsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/personOwnedTodoItemsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/todoItemIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updatePersonRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdatePersonRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateTagOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/tagIdentifierInRequest" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateTagRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateTagRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateTagRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateTagTodoItemsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/tagTodoItemsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/todoItemIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateTodoItemAssigneeRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/todoItemAssigneeRelationshipIdentifier" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/personIdentifierInRequest" + } + ], + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateTodoItemOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/todoItemIdentifierInRequest" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateTodoItemRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateTodoItemOwnerRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/todoItemOwnerRelationshipIdentifier" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/personIdentifierInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateTodoItemRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateTodoItemRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateTodoItemTagsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/todoItemTagsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/tagIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj b/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj index 0ccb4bbc5f..768a2de827 100644 --- a/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj +++ b/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj @@ -1,6 +1,8 @@ - net8.0;net6.0 + net9.0;net8.0 + true + GeneratedSwagger @@ -9,10 +11,15 @@ + + + + + diff --git a/src/Examples/JsonApiDotNetCoreExample/Program.cs b/src/Examples/JsonApiDotNetCoreExample/Program.cs index 52b27759e9..d2677ea781 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Program.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Program.cs @@ -3,21 +3,24 @@ using System.Text.Json.Serialization; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Diagnostics; +using JsonApiDotNetCore.OpenApi.Swashbuckle; +using JsonApiDotNetCoreExample; using JsonApiDotNetCoreExample.Data; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.Extensions.DependencyInjection.Extensions; -#if NET6_0 -using Microsoft.AspNetCore.Authentication; -#endif +using Scalar.AspNetCore; [assembly: ExcludeFromCodeCoverage] WebApplication app = CreateWebApplication(args); -await CreateDatabaseAsync(app.Services); +if (!IsGeneratingOpenApiDocumentAtBuildTime()) +{ + await CreateDatabaseAsync(app.Services); +} -app.Run(); +await app.RunAsync(); static WebApplication CreateWebApplication(string[] args) { @@ -34,10 +37,10 @@ static WebApplication CreateWebApplication(string[] args) // Configure the HTTP request pipeline. ConfigurePipeline(app); - if (CodeTimingSessionManager.IsEnabled) + if (CodeTimingSessionManager.IsEnabled && app.Logger.IsEnabled(LogLevel.Information)) { string timingResults = CodeTimingSessionManager.Current.GetResults(); - app.Logger.LogInformation($"Measurement results for application startup:{Environment.NewLine}{timingResults}"); + AppLog.LogStartupTimings(app.Logger, Environment.NewLine, timingResults); } return app; @@ -47,11 +50,7 @@ static void ConfigureServices(WebApplicationBuilder builder) { using IDisposable _ = CodeTimingSessionManager.Current.Measure("Configure services"); -#if NET6_0 - builder.Services.TryAddSingleton(); -#else builder.Services.TryAddSingleton(TimeProvider.System); -#endif builder.Services.AddDbContext(options => { @@ -77,6 +76,13 @@ static void ConfigureServices(WebApplicationBuilder builder) #endif }, discovery => discovery.AddCurrentAssembly()); } + + using (CodeTimingSessionManager.Current.Measure("AddOpenApiForJsonApi()")) + { +#pragma warning disable JADNC_OA_001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + builder.Services.AddOpenApiForJsonApi(options => options.DocumentFilter()); +#pragma warning restore JADNC_OA_001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + } } [Conditional("DEBUG")] @@ -98,9 +104,19 @@ static void ConfigurePipeline(WebApplication app) app.UseJsonApi(); } + app.UseSwagger(); + app.UseSwaggerUI(); + app.UseReDoc(); + app.MapScalarApiReference(options => options.OpenApiRoutePattern = "/swagger/{documentName}/swagger.json"); + app.MapControllers(); } +static bool IsGeneratingOpenApiDocumentAtBuildTime() +{ + return Environment.GetCommandLineArgs().Any(argument => argument.Contains("GetDocument.Insider")); +} + static async Task CreateDatabaseAsync(IServiceProvider serviceProvider) { await using AsyncServiceScope scope = serviceProvider.CreateAsyncScope(); diff --git a/src/Examples/JsonApiDotNetCoreExample/Properties/launchSettings.json b/src/Examples/JsonApiDotNetCoreExample/Properties/launchSettings.json index 54646922e1..82b89e1843 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Properties/launchSettings.json +++ b/src/Examples/JsonApiDotNetCoreExample/Properties/launchSettings.json @@ -12,7 +12,7 @@ "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, - "launchUrl": "api/todoItems?include=owner,assignee,tags&filter=equals(priority,'High')", + "launchUrl": "swagger", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } @@ -20,7 +20,7 @@ "Kestrel": { "commandName": "Project", "launchBrowser": true, - "launchUrl": "api/todoItems?include=owner,assignee,tags&filter=equals(priority,'High')", + "launchUrl": "swagger", "applicationUrl": "https://localhost:44340;http://localhost:14140", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" diff --git a/src/Examples/JsonApiDotNetCoreExample/SetOpenApiServerAtBuildTimeFilter.cs b/src/Examples/JsonApiDotNetCoreExample/SetOpenApiServerAtBuildTimeFilter.cs new file mode 100644 index 0000000000..894c0d0966 --- /dev/null +++ b/src/Examples/JsonApiDotNetCoreExample/SetOpenApiServerAtBuildTimeFilter.cs @@ -0,0 +1,25 @@ +using JetBrains.Annotations; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCoreExample; + +/// +/// This is normally not needed. It ensures the server URL is added to the OpenAPI file during build. +/// +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +internal sealed class SetOpenApiServerAtBuildTimeFilter(IHttpContextAccessor httpContextAccessor) : IDocumentFilter +{ + private readonly IHttpContextAccessor _httpContextAccessor = httpContextAccessor; + + public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) + { + if (_httpContextAccessor.HttpContext == null) + { + swaggerDoc.Servers.Add(new OpenApiServer + { + Url = "https://localhost:44340" + }); + } + } +} diff --git a/src/Examples/MultiDbContextExample/Data/DbContextA.cs b/src/Examples/MultiDbContextExample/Data/DbContextA.cs index 4efd10ea7b..32f6197600 100644 --- a/src/Examples/MultiDbContextExample/Data/DbContextA.cs +++ b/src/Examples/MultiDbContextExample/Data/DbContextA.cs @@ -5,7 +5,8 @@ namespace MultiDbContextExample.Data; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class DbContextA(DbContextOptions options) : DbContext(options) +public sealed class DbContextA(DbContextOptions options) + : DbContext(options) { public DbSet ResourceAs => Set(); } diff --git a/src/Examples/MultiDbContextExample/Data/DbContextB.cs b/src/Examples/MultiDbContextExample/Data/DbContextB.cs index faf50c0902..8759e28e91 100644 --- a/src/Examples/MultiDbContextExample/Data/DbContextB.cs +++ b/src/Examples/MultiDbContextExample/Data/DbContextB.cs @@ -5,7 +5,8 @@ namespace MultiDbContextExample.Data; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class DbContextB(DbContextOptions options) : DbContext(options) +public sealed class DbContextB(DbContextOptions options) + : DbContext(options) { public DbSet ResourceBs => Set(); } diff --git a/src/Examples/MultiDbContextExample/MultiDbContextExample.csproj b/src/Examples/MultiDbContextExample/MultiDbContextExample.csproj index 1f4645f323..611aeb37a5 100644 --- a/src/Examples/MultiDbContextExample/MultiDbContextExample.csproj +++ b/src/Examples/MultiDbContextExample/MultiDbContextExample.csproj @@ -1,6 +1,6 @@ - net8.0;net6.0 + net9.0;net8.0 diff --git a/src/Examples/MultiDbContextExample/Program.cs b/src/Examples/MultiDbContextExample/Program.cs index 2cf567b9b5..481e8f7118 100644 --- a/src/Examples/MultiDbContextExample/Program.cs +++ b/src/Examples/MultiDbContextExample/Program.cs @@ -52,7 +52,7 @@ await CreateDatabaseAsync(app.Services); -app.Run(); +await app.RunAsync(); [Conditional("DEBUG")] static void SetDbContextDebugOptions(DbContextOptionsBuilder options) diff --git a/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj b/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj index c5b18320f0..15a485c08f 100644 --- a/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj +++ b/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj @@ -1,6 +1,6 @@ - net8.0;net6.0 + net9.0;net8.0 diff --git a/src/Examples/NoEntityFrameworkExample/Program.cs b/src/Examples/NoEntityFrameworkExample/Program.cs index f21d116e5f..8eff35d7a9 100755 --- a/src/Examples/NoEntityFrameworkExample/Program.cs +++ b/src/Examples/NoEntityFrameworkExample/Program.cs @@ -35,4 +35,4 @@ app.UseJsonApi(); app.MapControllers(); -app.Run(); +await app.RunAsync(); diff --git a/src/Examples/NoEntityFrameworkExample/Repositories/InMemoryResourceRepository.cs b/src/Examples/NoEntityFrameworkExample/Repositories/InMemoryResourceRepository.cs index 9d0852ad7f..4feb370858 100644 --- a/src/Examples/NoEntityFrameworkExample/Repositories/InMemoryResourceRepository.cs +++ b/src/Examples/NoEntityFrameworkExample/Repositories/InMemoryResourceRepository.cs @@ -32,7 +32,7 @@ public Task> GetAsync(QueryLayer queryLayer, Canc IEnumerable dataSource = GetDataSource(); IEnumerable resources = _queryLayerToLinqConverter.ApplyQueryLayer(queryLayer, dataSource); - return Task.FromResult>(resources.ToList()); + return Task.FromResult>(resources.ToArray().AsReadOnly()); } /// diff --git a/src/Examples/NoEntityFrameworkExample/Services/InMemoryResourceService.cs b/src/Examples/NoEntityFrameworkExample/Services/InMemoryResourceService.cs index ee9d2196e9..0dcc5d9905 100644 --- a/src/Examples/NoEntityFrameworkExample/Services/InMemoryResourceService.cs +++ b/src/Examples/NoEntityFrameworkExample/Services/InMemoryResourceService.cs @@ -31,7 +31,7 @@ namespace NoEntityFrameworkExample.Services; /// /// The resource identifier type. /// -public abstract class InMemoryResourceService( +public abstract partial class InMemoryResourceService( IJsonApiOptions options, IResourceGraph resourceGraph, IQueryLayerComposer queryLayerComposer, IPaginationContext paginationContext, IEnumerable constraintProviders, IQueryableBuilder queryableBuilder, IReadOnlyModel entityModel, ILoggerFactory loggerFactory) : IResourceQueryService @@ -40,7 +40,7 @@ public abstract class InMemoryResourceService( private readonly IJsonApiOptions _options = options; private readonly IQueryLayerComposer _queryLayerComposer = queryLayerComposer; private readonly IPaginationContext _paginationContext = paginationContext; - private readonly IEnumerable _constraintProviders = constraintProviders; + private readonly IQueryConstraintProvider[] _constraintProviders = constraintProviders as IQueryConstraintProvider[] ?? constraintProviders.ToArray(); private readonly ILogger> _logger = loggerFactory.CreateLogger>(); private readonly ResourceType _resourceType = resourceGraph.GetResourceType(); private readonly QueryLayerToLinqConverter _queryLayerToLinqConverter = new(entityModel, queryableBuilder); @@ -58,14 +58,14 @@ public Task> GetAsync(CancellationToken cancellat QueryLayer queryLayer = _queryLayerComposer.ComposeFromConstraints(_resourceType); IEnumerable dataSource = GetDataSource(_resourceType).Cast(); - List resources = _queryLayerToLinqConverter.ApplyQueryLayer(queryLayer, dataSource).ToList(); + TResource[] resources = _queryLayerToLinqConverter.ApplyQueryLayer(queryLayer, dataSource).ToArray(); - if (queryLayer.Pagination?.PageSize?.Value == resources.Count) + if (queryLayer.Pagination?.PageSize?.Value == resources.Length) { _paginationContext.IsPageFull = true; } - return Task.FromResult>(resources); + return Task.FromResult>(resources.AsReadOnly()); } private void LogFiltersInTopScope() @@ -87,7 +87,7 @@ private void LogFiltersInTopScope() if (filter != null) { - _logger.LogInformation($"Incoming top-level filter from query string: {filter}"); + LogIncomingFilter(filter); } } @@ -195,4 +195,7 @@ private void SetNonPrimaryTotalCount([DisallowNull] TId id, RelationshipAttribut } protected abstract IEnumerable GetDataSource(ResourceType resourceType); + + [LoggerMessage(Level = LogLevel.Information, Message = "Incoming top-level filter from query string: {Filter}")] + private partial void LogIncomingFilter(FilterExpression filter); } diff --git a/src/Examples/OpenApiKiotaClientExample/ColoredConsoleLogHttpMessageHandler.cs b/src/Examples/OpenApiKiotaClientExample/ColoredConsoleLogHttpMessageHandler.cs new file mode 100644 index 0000000000..e13aff5a4d --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/ColoredConsoleLogHttpMessageHandler.cs @@ -0,0 +1,67 @@ +using JetBrains.Annotations; + +namespace OpenApiKiotaClientExample; + +/// +/// Writes incoming and outgoing HTTP messages to the console. +/// +internal sealed class ColoredConsoleLogHttpMessageHandler : DelegatingHandler +{ + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { +#if DEBUG + await LogRequestAsync(request, cancellationToken); +#endif + + HttpResponseMessage response = await base.SendAsync(request, cancellationToken); + +#if DEBUG + await LogResponseAsync(response, cancellationToken); +#endif + + return response; + } + + [UsedImplicitly] + private static async Task LogRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + using var _ = new ConsoleColorScope(ConsoleColor.Green); + + Console.WriteLine($"--> {request}"); + string? requestBody = request.Content != null ? await request.Content.ReadAsStringAsync(cancellationToken) : null; + + if (!string.IsNullOrEmpty(requestBody)) + { + Console.WriteLine(); + Console.WriteLine(requestBody); + } + } + + [UsedImplicitly] + private static async Task LogResponseAsync(HttpResponseMessage response, CancellationToken cancellationToken) + { + using var _ = new ConsoleColorScope(ConsoleColor.Cyan); + + Console.WriteLine($"<-- {response}"); + string responseBody = await response.Content.ReadAsStringAsync(cancellationToken); + + if (!string.IsNullOrEmpty(responseBody)) + { + Console.WriteLine(); + Console.WriteLine(responseBody); + } + } + + private sealed class ConsoleColorScope : IDisposable + { + public ConsoleColorScope(ConsoleColor foregroundColor) + { + Console.ForegroundColor = foregroundColor; + } + + public void Dispose() + { + Console.ResetColor(); + } + } +} diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/ApiRequestBuilder.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/ApiRequestBuilder.cs new file mode 100644 index 0000000000..3d0f7361e7 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/ApiRequestBuilder.cs @@ -0,0 +1,66 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaClientExample.GeneratedCode.Api.Operations; +using OpenApiKiotaClientExample.GeneratedCode.Api.People; +using OpenApiKiotaClientExample.GeneratedCode.Api.Tags; +using OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Api +{ + /// + /// Builds and executes requests for operations under \api + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ApiRequestBuilder : BaseRequestBuilder + { + /// The operations property + public global::OpenApiKiotaClientExample.GeneratedCode.Api.Operations.OperationsRequestBuilder Operations + { + get => new global::OpenApiKiotaClientExample.GeneratedCode.Api.Operations.OperationsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The people property + public global::OpenApiKiotaClientExample.GeneratedCode.Api.People.PeopleRequestBuilder People + { + get => new global::OpenApiKiotaClientExample.GeneratedCode.Api.People.PeopleRequestBuilder(PathParameters, RequestAdapter); + } + + /// The tags property + public global::OpenApiKiotaClientExample.GeneratedCode.Api.Tags.TagsRequestBuilder Tags + { + get => new global::OpenApiKiotaClientExample.GeneratedCode.Api.Tags.TagsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The todoItems property + public global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.TodoItemsRequestBuilder TodoItems + { + get => new global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.TodoItemsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ApiRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ApiRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/Operations/OperationsRequestBuilder.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/Operations/OperationsRequestBuilder.cs new file mode 100644 index 0000000000..96f21c5a24 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/Operations/OperationsRequestBuilder.cs @@ -0,0 +1,94 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaClientExample.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Api.Operations +{ + /// + /// Builds and executes requests for operations under \api\operations + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OperationsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public OperationsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/operations", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public OperationsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/operations", rawUrl) + { + } + + /// + /// Performs multiple mutations in a linear and atomic manner. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaClientExample.GeneratedCode.Models.OperationsRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.OperationsResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Performs multiple mutations in a linear and atomic manner. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaClientExample.GeneratedCode.Models.OperationsRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=atomic;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=atomic;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaClientExample.GeneratedCode.Api.Operations.OperationsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaClientExample.GeneratedCode.Api.Operations.OperationsRequestBuilder(rawUrl, RequestAdapter); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/People/Item/AssignedTodoItems/AssignedTodoItemsRequestBuilder.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/People/Item/AssignedTodoItems/AssignedTodoItemsRequestBuilder.cs new file mode 100644 index 0000000000..7bcc782af9 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/People/Item/AssignedTodoItems/AssignedTodoItemsRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaClientExample.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.AssignedTodoItems +{ + /// + /// Builds and executes requests for operations under \api\people\{id}\assignedTodoItems + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AssignedTodoItemsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public AssignedTodoItemsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/people/{id}/assignedTodoItems{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public AssignedTodoItemsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/people/{id}/assignedTodoItems{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related todoItems of an individual person's assignedTodoItems relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related todoItems of an individual person's assignedTodoItems relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.AssignedTodoItems.AssignedTodoItemsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.AssignedTodoItems.AssignedTodoItemsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related todoItems of an individual person's assignedTodoItems relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AssignedTodoItemsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AssignedTodoItemsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/People/Item/OwnedTodoItems/OwnedTodoItemsRequestBuilder.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/People/Item/OwnedTodoItems/OwnedTodoItemsRequestBuilder.cs new file mode 100644 index 0000000000..2981e5fa65 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/People/Item/OwnedTodoItems/OwnedTodoItemsRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaClientExample.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.OwnedTodoItems +{ + /// + /// Builds and executes requests for operations under \api\people\{id}\ownedTodoItems + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OwnedTodoItemsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public OwnedTodoItemsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/people/{id}/ownedTodoItems{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public OwnedTodoItemsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/people/{id}/ownedTodoItems{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related todoItems of an individual person's ownedTodoItems relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related todoItems of an individual person's ownedTodoItems relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.OwnedTodoItems.OwnedTodoItemsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.OwnedTodoItems.OwnedTodoItemsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related todoItems of an individual person's ownedTodoItems relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OwnedTodoItemsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OwnedTodoItemsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/People/Item/PeopleItemRequestBuilder.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/People/Item/PeopleItemRequestBuilder.cs new file mode 100644 index 0000000000..567ed904c8 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/People/Item/PeopleItemRequestBuilder.cs @@ -0,0 +1,230 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.AssignedTodoItems; +using OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.OwnedTodoItems; +using OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.Relationships; +using OpenApiKiotaClientExample.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Api.People.Item +{ + /// + /// Builds and executes requests for operations under \api\people\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class PeopleItemRequestBuilder : BaseRequestBuilder + { + /// The assignedTodoItems property + public global::OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.AssignedTodoItems.AssignedTodoItemsRequestBuilder AssignedTodoItems + { + get => new global::OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.AssignedTodoItems.AssignedTodoItemsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The ownedTodoItems property + public global::OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.OwnedTodoItems.OwnedTodoItemsRequestBuilder OwnedTodoItems + { + get => new global::OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.OwnedTodoItems.OwnedTodoItemsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The relationships property + public global::OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public PeopleItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/people/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public PeopleItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/people/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing person by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual person by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.PrimaryPersonResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing person. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdatePersonRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.PrimaryPersonResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing person by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual person by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing person. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdatePersonRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.PeopleItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.PeopleItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual person by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class PeopleItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class PeopleItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing person. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class PeopleItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/People/Item/Relationships/AssignedTodoItems/AssignedTodoItemsRequestBuilder.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/People/Item/Relationships/AssignedTodoItems/AssignedTodoItemsRequestBuilder.cs new file mode 100644 index 0000000000..14c018d51f --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/People/Item/Relationships/AssignedTodoItems/AssignedTodoItemsRequestBuilder.cs @@ -0,0 +1,248 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaClientExample.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.Relationships.AssignedTodoItems +{ + /// + /// Builds and executes requests for operations under \api\people\{id}\relationships\assignedTodoItems + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AssignedTodoItemsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public AssignedTodoItemsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/people/{id}/relationships/assignedTodoItems{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public AssignedTodoItemsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/people/{id}/relationships/assignedTodoItems{?query*}", rawUrl) + { + } + + /// + /// Removes existing todoItems from the assignedTodoItems relationship of an individual person. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task DeleteAsync(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToDeleteRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related todoItem identities of an individual person's assignedTodoItems relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns existing todoItems to the assignedTodoItems relationship of an individual person. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Adds existing todoItems to the assignedTodoItems relationship of an individual person. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Removes existing todoItems from the assignedTodoItems relationship of an individual person. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Retrieves the related todoItem identities of an individual person's assignedTodoItems relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns existing todoItems to the assignedTodoItems relationship of an individual person. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Adds existing todoItems to the assignedTodoItems relationship of an individual person. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.Relationships.AssignedTodoItems.AssignedTodoItemsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.Relationships.AssignedTodoItems.AssignedTodoItemsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related todoItem identities of an individual person's assignedTodoItems relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AssignedTodoItemsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AssignedTodoItemsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/People/Item/Relationships/OwnedTodoItems/OwnedTodoItemsRequestBuilder.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/People/Item/Relationships/OwnedTodoItems/OwnedTodoItemsRequestBuilder.cs new file mode 100644 index 0000000000..9f27d97c3b --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/People/Item/Relationships/OwnedTodoItems/OwnedTodoItemsRequestBuilder.cs @@ -0,0 +1,248 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaClientExample.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.Relationships.OwnedTodoItems +{ + /// + /// Builds and executes requests for operations under \api\people\{id}\relationships\ownedTodoItems + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OwnedTodoItemsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public OwnedTodoItemsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/people/{id}/relationships/ownedTodoItems{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public OwnedTodoItemsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/people/{id}/relationships/ownedTodoItems{?query*}", rawUrl) + { + } + + /// + /// Removes existing todoItems from the ownedTodoItems relationship of an individual person. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task DeleteAsync(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToDeleteRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related todoItem identities of an individual person's ownedTodoItems relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns existing todoItems to the ownedTodoItems relationship of an individual person. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Adds existing todoItems to the ownedTodoItems relationship of an individual person. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Removes existing todoItems from the ownedTodoItems relationship of an individual person. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Retrieves the related todoItem identities of an individual person's ownedTodoItems relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns existing todoItems to the ownedTodoItems relationship of an individual person. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Adds existing todoItems to the ownedTodoItems relationship of an individual person. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.Relationships.OwnedTodoItems.OwnedTodoItemsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.Relationships.OwnedTodoItems.OwnedTodoItemsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related todoItem identities of an individual person's ownedTodoItems relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OwnedTodoItemsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OwnedTodoItemsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/People/Item/Relationships/RelationshipsRequestBuilder.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/People/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..2c9e9beafe --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/People/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,52 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.Relationships.AssignedTodoItems; +using OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.Relationships.OwnedTodoItems; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \api\people\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The assignedTodoItems property + public global::OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.Relationships.AssignedTodoItems.AssignedTodoItemsRequestBuilder AssignedTodoItems + { + get => new global::OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.Relationships.AssignedTodoItems.AssignedTodoItemsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The ownedTodoItems property + public global::OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.Relationships.OwnedTodoItems.OwnedTodoItemsRequestBuilder OwnedTodoItems + { + get => new global::OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.Relationships.OwnedTodoItems.OwnedTodoItemsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/people/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/people/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/People/PeopleRequestBuilder.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/People/PeopleRequestBuilder.cs new file mode 100644 index 0000000000..3a36d323c4 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/People/PeopleRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaClientExample.GeneratedCode.Api.People.Item; +using OpenApiKiotaClientExample.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Api.People +{ + /// + /// Builds and executes requests for operations under \api\people + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class PeopleRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaClientExample.GeneratedCode.api.people.item collection + /// The identifier of the person to retrieve. + /// A + public global::OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.PeopleItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaClientExample.GeneratedCode.Api.People.Item.PeopleItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public PeopleRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/people{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public PeopleRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/people{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of people. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new person. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaClientExample.GeneratedCode.Models.CreatePersonRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.PrimaryPersonResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of people. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new person. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaClientExample.GeneratedCode.Models.CreatePersonRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaClientExample.GeneratedCode.Api.People.PeopleRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaClientExample.GeneratedCode.Api.People.PeopleRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of people. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class PeopleRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class PeopleRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new person. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class PeopleRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/Tags/Item/Relationships/RelationshipsRequestBuilder.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/Tags/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..ecf2f5cc86 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/Tags/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaClientExample.GeneratedCode.Api.Tags.Item.Relationships.TodoItems; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Api.Tags.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \api\tags\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The todoItems property + public global::OpenApiKiotaClientExample.GeneratedCode.Api.Tags.Item.Relationships.TodoItems.TodoItemsRequestBuilder TodoItems + { + get => new global::OpenApiKiotaClientExample.GeneratedCode.Api.Tags.Item.Relationships.TodoItems.TodoItemsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/tags/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/tags/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/Tags/Item/Relationships/TodoItems/TodoItemsRequestBuilder.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/Tags/Item/Relationships/TodoItems/TodoItemsRequestBuilder.cs new file mode 100644 index 0000000000..6020933f3d --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/Tags/Item/Relationships/TodoItems/TodoItemsRequestBuilder.cs @@ -0,0 +1,248 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaClientExample.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Api.Tags.Item.Relationships.TodoItems +{ + /// + /// Builds and executes requests for operations under \api\tags\{id}\relationships\todoItems + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TodoItemsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public TodoItemsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/tags/{id}/relationships/todoItems{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public TodoItemsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/tags/{id}/relationships/todoItems{?query*}", rawUrl) + { + } + + /// + /// Removes existing todoItems from the todoItems relationship of an individual tag. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task DeleteAsync(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToDeleteRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related todoItem identities of an individual tag's todoItems relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns existing todoItems to the todoItems relationship of an individual tag. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Adds existing todoItems to the todoItems relationship of an individual tag. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Removes existing todoItems from the todoItems relationship of an individual tag. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Retrieves the related todoItem identities of an individual tag's todoItems relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns existing todoItems to the todoItems relationship of an individual tag. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Adds existing todoItems to the todoItems relationship of an individual tag. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaClientExample.GeneratedCode.Api.Tags.Item.Relationships.TodoItems.TodoItemsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaClientExample.GeneratedCode.Api.Tags.Item.Relationships.TodoItems.TodoItemsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related todoItem identities of an individual tag's todoItems relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TodoItemsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TodoItemsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/Tags/Item/TagsItemRequestBuilder.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/Tags/Item/TagsItemRequestBuilder.cs new file mode 100644 index 0000000000..5321238e2b --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/Tags/Item/TagsItemRequestBuilder.cs @@ -0,0 +1,223 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaClientExample.GeneratedCode.Api.Tags.Item.Relationships; +using OpenApiKiotaClientExample.GeneratedCode.Api.Tags.Item.TodoItems; +using OpenApiKiotaClientExample.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Api.Tags.Item +{ + /// + /// Builds and executes requests for operations under \api\tags\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TagsItemRequestBuilder : BaseRequestBuilder + { + /// The relationships property + public global::OpenApiKiotaClientExample.GeneratedCode.Api.Tags.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaClientExample.GeneratedCode.Api.Tags.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The todoItems property + public global::OpenApiKiotaClientExample.GeneratedCode.Api.Tags.Item.TodoItems.TodoItemsRequestBuilder TodoItems + { + get => new global::OpenApiKiotaClientExample.GeneratedCode.Api.Tags.Item.TodoItems.TodoItemsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public TagsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/tags/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public TagsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/tags/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing tag by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual tag by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.PrimaryTagResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing tag. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTagRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.PrimaryTagResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing tag by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual tag by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing tag. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTagRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaClientExample.GeneratedCode.Api.Tags.Item.TagsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaClientExample.GeneratedCode.Api.Tags.Item.TagsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual tag by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TagsItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TagsItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing tag. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TagsItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/Tags/Item/TodoItems/TodoItemsRequestBuilder.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/Tags/Item/TodoItems/TodoItemsRequestBuilder.cs new file mode 100644 index 0000000000..c5c673d844 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/Tags/Item/TodoItems/TodoItemsRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaClientExample.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Api.Tags.Item.TodoItems +{ + /// + /// Builds and executes requests for operations under \api\tags\{id}\todoItems + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TodoItemsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public TodoItemsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/tags/{id}/todoItems{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public TodoItemsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/tags/{id}/todoItems{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related todoItems of an individual tag's todoItems relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related todoItems of an individual tag's todoItems relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaClientExample.GeneratedCode.Api.Tags.Item.TodoItems.TodoItemsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaClientExample.GeneratedCode.Api.Tags.Item.TodoItems.TodoItemsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related todoItems of an individual tag's todoItems relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TodoItemsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TodoItemsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/Tags/TagsRequestBuilder.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/Tags/TagsRequestBuilder.cs new file mode 100644 index 0000000000..ccc88d242c --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/Tags/TagsRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaClientExample.GeneratedCode.Api.Tags.Item; +using OpenApiKiotaClientExample.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Api.Tags +{ + /// + /// Builds and executes requests for operations under \api\tags + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TagsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaClientExample.GeneratedCode.api.tags.item collection + /// The identifier of the tag to retrieve. + /// A + public global::OpenApiKiotaClientExample.GeneratedCode.Api.Tags.Item.TagsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaClientExample.GeneratedCode.Api.Tags.Item.TagsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public TagsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/tags{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public TagsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/tags{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of tags. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.TagCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new tag. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaClientExample.GeneratedCode.Models.CreateTagRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.PrimaryTagResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of tags. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new tag. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaClientExample.GeneratedCode.Models.CreateTagRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaClientExample.GeneratedCode.Api.Tags.TagsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaClientExample.GeneratedCode.Api.Tags.TagsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of tags. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TagsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TagsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new tag. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TagsRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/Assignee/AssigneeRequestBuilder.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/Assignee/AssigneeRequestBuilder.cs new file mode 100644 index 0000000000..10601bcef3 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/Assignee/AssigneeRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaClientExample.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Assignee +{ + /// + /// Builds and executes requests for operations under \api\todoItems\{id}\assignee + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AssigneeRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public AssigneeRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/todoItems/{id}/assignee{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public AssigneeRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/todoItems/{id}/assignee{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related person of an individual todoItem's assignee relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.NullableSecondaryPersonResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related person of an individual todoItem's assignee relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Assignee.AssigneeRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Assignee.AssigneeRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related person of an individual todoItem's assignee relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AssigneeRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AssigneeRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/Owner/OwnerRequestBuilder.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/Owner/OwnerRequestBuilder.cs new file mode 100644 index 0000000000..8fe72c9e38 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/Owner/OwnerRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaClientExample.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Owner +{ + /// + /// Builds and executes requests for operations under \api\todoItems\{id}\owner + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OwnerRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public OwnerRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/todoItems/{id}/owner{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public OwnerRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/todoItems/{id}/owner{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related person of an individual todoItem's owner relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.SecondaryPersonResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related person of an individual todoItem's owner relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Owner.OwnerRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Owner.OwnerRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related person of an individual todoItem's owner relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OwnerRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OwnerRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/Relationships/Assignee/AssigneeRequestBuilder.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/Relationships/Assignee/AssigneeRequestBuilder.cs new file mode 100644 index 0000000000..5d775fbf73 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/Relationships/Assignee/AssigneeRequestBuilder.cs @@ -0,0 +1,168 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaClientExample.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Relationships.Assignee +{ + /// + /// Builds and executes requests for operations under \api\todoItems\{id}\relationships\assignee + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AssigneeRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public AssigneeRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/todoItems/{id}/relationships/assignee{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public AssigneeRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/todoItems/{id}/relationships/assignee{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related person identity of an individual todoItem's assignee relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.NullablePersonIdentifierResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Clears or assigns an existing person to the assignee relationship of an individual todoItem. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaClientExample.GeneratedCode.Models.NullableToOnePersonInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related person identity of an individual todoItem's assignee relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Clears or assigns an existing person to the assignee relationship of an individual todoItem. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaClientExample.GeneratedCode.Models.NullableToOnePersonInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Relationships.Assignee.AssigneeRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Relationships.Assignee.AssigneeRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related person identity of an individual todoItem's assignee relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AssigneeRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AssigneeRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/Relationships/Owner/OwnerRequestBuilder.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/Relationships/Owner/OwnerRequestBuilder.cs new file mode 100644 index 0000000000..abe58c712f --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/Relationships/Owner/OwnerRequestBuilder.cs @@ -0,0 +1,168 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaClientExample.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Relationships.Owner +{ + /// + /// Builds and executes requests for operations under \api\todoItems\{id}\relationships\owner + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OwnerRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public OwnerRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/todoItems/{id}/relationships/owner{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public OwnerRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/todoItems/{id}/relationships/owner{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related person identity of an individual todoItem's owner relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns an existing person to the owner relationship of an individual todoItem. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToOnePersonInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related person identity of an individual todoItem's owner relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns an existing person to the owner relationship of an individual todoItem. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToOnePersonInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Relationships.Owner.OwnerRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Relationships.Owner.OwnerRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related person identity of an individual todoItem's owner relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OwnerRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OwnerRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/Relationships/RelationshipsRequestBuilder.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..0737f8ce56 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Relationships.Assignee; +using OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Relationships.Owner; +using OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Relationships.Tags; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \api\todoItems\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The assignee property + public global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Relationships.Assignee.AssigneeRequestBuilder Assignee + { + get => new global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Relationships.Assignee.AssigneeRequestBuilder(PathParameters, RequestAdapter); + } + + /// The owner property + public global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Relationships.Owner.OwnerRequestBuilder Owner + { + get => new global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Relationships.Owner.OwnerRequestBuilder(PathParameters, RequestAdapter); + } + + /// The tags property + public global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Relationships.Tags.TagsRequestBuilder Tags + { + get => new global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Relationships.Tags.TagsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/todoItems/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/todoItems/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/Relationships/Tags/TagsRequestBuilder.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/Relationships/Tags/TagsRequestBuilder.cs new file mode 100644 index 0000000000..0dc145b7f0 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/Relationships/Tags/TagsRequestBuilder.cs @@ -0,0 +1,248 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaClientExample.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Relationships.Tags +{ + /// + /// Builds and executes requests for operations under \api\todoItems\{id}\relationships\tags + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TagsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public TagsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/todoItems/{id}/relationships/tags{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public TagsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/todoItems/{id}/relationships/tags{?query*}", rawUrl) + { + } + + /// + /// Removes existing tags from the tags relationship of an individual todoItem. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task DeleteAsync(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTagInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToDeleteRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related tag identities of an individual todoItem's tags relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.TagIdentifierCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns existing tags to the tags relationship of an individual todoItem. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTagInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Adds existing tags to the tags relationship of an individual todoItem. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTagInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Removes existing tags from the tags relationship of an individual todoItem. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTagInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Retrieves the related tag identities of an individual todoItem's tags relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns existing tags to the tags relationship of an individual todoItem. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTagInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Adds existing tags to the tags relationship of an individual todoItem. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTagInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Relationships.Tags.TagsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Relationships.Tags.TagsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related tag identities of an individual todoItem's tags relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TagsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TagsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/Tags/TagsRequestBuilder.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/Tags/TagsRequestBuilder.cs new file mode 100644 index 0000000000..bddab801c4 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/Tags/TagsRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaClientExample.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Tags +{ + /// + /// Builds and executes requests for operations under \api\todoItems\{id}\tags + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TagsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public TagsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/todoItems/{id}/tags{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public TagsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/todoItems/{id}/tags{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related tags of an individual todoItem's tags relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.TagCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related tags of an individual todoItem's tags relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Tags.TagsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Tags.TagsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related tags of an individual todoItem's tags relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TagsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TagsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/TodoItemsItemRequestBuilder.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/TodoItemsItemRequestBuilder.cs new file mode 100644 index 0000000000..2383afe1a0 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/Item/TodoItemsItemRequestBuilder.cs @@ -0,0 +1,237 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Assignee; +using OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Owner; +using OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Relationships; +using OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Tags; +using OpenApiKiotaClientExample.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item +{ + /// + /// Builds and executes requests for operations under \api\todoItems\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TodoItemsItemRequestBuilder : BaseRequestBuilder + { + /// The assignee property + public global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Assignee.AssigneeRequestBuilder Assignee + { + get => new global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Assignee.AssigneeRequestBuilder(PathParameters, RequestAdapter); + } + + /// The owner property + public global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Owner.OwnerRequestBuilder Owner + { + get => new global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Owner.OwnerRequestBuilder(PathParameters, RequestAdapter); + } + + /// The relationships property + public global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The tags property + public global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Tags.TagsRequestBuilder Tags + { + get => new global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.Tags.TagsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public TodoItemsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/todoItems/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public TodoItemsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/todoItems/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing todoItem by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual todoItem by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.PrimaryTodoItemResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing todoItem. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTodoItemRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.PrimaryTodoItemResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing todoItem by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual todoItem by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing todoItem. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTodoItemRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.TodoItemsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.TodoItemsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual todoItem by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TodoItemsItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TodoItemsItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing todoItem. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TodoItemsItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/TodoItemsRequestBuilder.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/TodoItemsRequestBuilder.cs new file mode 100644 index 0000000000..bc3feeaf22 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Api/TodoItems/TodoItemsRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item; +using OpenApiKiotaClientExample.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems +{ + /// + /// Builds and executes requests for operations under \api\todoItems + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TodoItemsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaClientExample.GeneratedCode.api.todoItems.item collection + /// The identifier of the todoItem to retrieve. + /// A + public global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.TodoItemsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.Item.TodoItemsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public TodoItemsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/todoItems{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public TodoItemsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/todoItems{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of todoItems. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new todoItem. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaClientExample.GeneratedCode.Models.CreateTodoItemRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaClientExample.GeneratedCode.Models.PrimaryTodoItemResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of todoItems. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new todoItem. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaClientExample.GeneratedCode.Models.CreateTodoItemRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.TodoItemsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaClientExample.GeneratedCode.Api.TodoItems.TodoItemsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of todoItems. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TodoItemsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TodoItemsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new todoItem. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TodoItemsRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/ExampleApiClient.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/ExampleApiClient.cs new file mode 100644 index 0000000000..15ea897045 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/ExampleApiClient.cs @@ -0,0 +1,54 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using Microsoft.Kiota.Serialization.Form; +using Microsoft.Kiota.Serialization.Json; +using Microsoft.Kiota.Serialization.Multipart; +using Microsoft.Kiota.Serialization.Text; +using OpenApiKiotaClientExample.GeneratedCode.Api; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode +{ + /// + /// The main entry point of the SDK, exposes the configuration and the fluent API. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ExampleApiClient : BaseRequestBuilder + { + /// The api property + public global::OpenApiKiotaClientExample.GeneratedCode.Api.ApiRequestBuilder Api + { + get => new global::OpenApiKiotaClientExample.GeneratedCode.Api.ApiRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The backing store to use for the models. + /// The request adapter to use to execute the requests. + public ExampleApiClient(IRequestAdapter requestAdapter, IBackingStoreFactory backingStore = default) : base(requestAdapter, "{+baseurl}", new Dictionary()) + { + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + if (string.IsNullOrEmpty(RequestAdapter.BaseUrl)) + { + RequestAdapter.BaseUrl = "https://localhost:44340"; + } + PathParameters.TryAdd("baseurl", RequestAdapter.BaseUrl); + RequestAdapter.EnableBackingStore(backingStore); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AddOperationCode.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AddOperationCode.cs new file mode 100644 index 0000000000..eb7b72025a --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AddOperationCode.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum AddOperationCode + #pragma warning restore CS1591 + { + [EnumMember(Value = "add")] + #pragma warning disable CS1591 + Add, + #pragma warning restore CS1591 + } +} diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AddToPersonAssignedTodoItemsRelationshipOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AddToPersonAssignedTodoItemsRelationshipOperation.cs new file mode 100644 index 0000000000..e45dc51ebf --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AddToPersonAssignedTodoItemsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AddToPersonAssignedTodoItemsRelationshipOperation : global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.AddOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonAssignedTodoItemsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.AddToPersonAssignedTodoItemsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.AddToPersonAssignedTodoItemsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonAssignedTodoItemsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AddToPersonOwnedTodoItemsRelationshipOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AddToPersonOwnedTodoItemsRelationshipOperation.cs new file mode 100644 index 0000000000..23f7ef0320 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AddToPersonOwnedTodoItemsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AddToPersonOwnedTodoItemsRelationshipOperation : global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.AddOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonOwnedTodoItemsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.AddToPersonOwnedTodoItemsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.AddToPersonOwnedTodoItemsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonOwnedTodoItemsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AddToTagTodoItemsRelationshipOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AddToTagTodoItemsRelationshipOperation.cs new file mode 100644 index 0000000000..960e6aa8dc --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AddToTagTodoItemsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AddToTagTodoItemsRelationshipOperation : global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.AddOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TagTodoItemsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.AddToTagTodoItemsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.AddToTagTodoItemsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.TagTodoItemsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AddToTodoItemTagsRelationshipOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AddToTodoItemTagsRelationshipOperation.cs new file mode 100644 index 0000000000..69f97a3707 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AddToTodoItemTagsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AddToTodoItemTagsRelationshipOperation : global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.AddOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemTagsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.AddToTodoItemTagsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.AddToTodoItemTagsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.TagIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemTagsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AtomicOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AtomicOperation.cs new file mode 100644 index 0000000000..3703a87e02 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AtomicOperation.cs @@ -0,0 +1,106 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AtomicOperation : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The openapiDiscriminator property + public string? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AtomicOperation() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "addPerson" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.CreatePersonOperation(), + "addTag" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.CreateTagOperation(), + "addTodoItem" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.CreateTodoItemOperation(), + "addToPersonAssignedTodoItems" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.AddToPersonAssignedTodoItemsRelationshipOperation(), + "addToPersonOwnedTodoItems" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.AddToPersonOwnedTodoItemsRelationshipOperation(), + "addToTagTodoItems" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.AddToTagTodoItemsRelationshipOperation(), + "addToTodoItemTags" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.AddToTodoItemTagsRelationshipOperation(), + "removeFromPersonAssignedTodoItems" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.RemoveFromPersonAssignedTodoItemsRelationshipOperation(), + "removeFromPersonOwnedTodoItems" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.RemoveFromPersonOwnedTodoItemsRelationshipOperation(), + "removeFromTagTodoItems" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.RemoveFromTagTodoItemsRelationshipOperation(), + "removeFromTodoItemTags" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.RemoveFromTodoItemTagsRelationshipOperation(), + "removePerson" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.DeletePersonOperation(), + "removeTag" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.DeleteTagOperation(), + "removeTodoItem" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.DeleteTodoItemOperation(), + "updatePerson" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdatePersonOperation(), + "updatePersonAssignedTodoItems" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdatePersonAssignedTodoItemsRelationshipOperation(), + "updatePersonOwnedTodoItems" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdatePersonOwnedTodoItemsRelationshipOperation(), + "updateTag" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTagOperation(), + "updateTagTodoItems" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTagTodoItemsRelationshipOperation(), + "updateTodoItem" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTodoItemOperation(), + "updateTodoItemAssignee" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTodoItemAssigneeRelationshipOperation(), + "updateTodoItemOwner" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTodoItemOwnerRelationshipOperation(), + "updateTodoItemTags" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTodoItemTagsRelationshipOperation(), + _ => new global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteStringValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AtomicResult.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AtomicResult.cs new file mode 100644 index 0000000000..8be7f5afd5 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AtomicResult.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AtomicResult : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AtomicResult() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicResult CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicResult(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInCreatePersonRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInCreatePersonRequest.cs new file mode 100644 index 0000000000..b26154383a --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInCreatePersonRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreatePersonRequest : global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The firstName property + public string? FirstName + { + get { return BackingStore?.Get("firstName"); } + set { BackingStore?.Set("firstName", value); } + } + + /// The lastName property + public string? LastName + { + get { return BackingStore?.Get("lastName"); } + set { BackingStore?.Set("lastName", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInCreatePersonRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInCreatePersonRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "firstName", n => { FirstName = n.GetStringValue(); } }, + { "lastName", n => { LastName = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("firstName", FirstName); + writer.WriteStringValue("lastName", LastName); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInCreateRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInCreateRequest.cs new file mode 100644 index 0000000000..19fb0fdd8b --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInCreateRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "people" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInCreatePersonRequest(), + "tags" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInCreateTagRequest(), + "todoItems" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInCreateTodoItemRequest(), + _ => new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInCreateTagRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInCreateTagRequest.cs new file mode 100644 index 0000000000..b191d1ad18 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInCreateTagRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateTagRequest : global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInCreateTagRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInCreateTagRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInCreateTodoItemRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInCreateTodoItemRequest.cs new file mode 100644 index 0000000000..d783a50dfa --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInCreateTodoItemRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateTodoItemRequest : global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The description property + public string? Description + { + get { return BackingStore?.Get("description"); } + set { BackingStore?.Set("description", value); } + } + + /// The durationInHours property + public long? DurationInHours + { + get { return BackingStore?.Get("durationInHours"); } + set { BackingStore?.Set("durationInHours", value); } + } + + /// The priority property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemPriority? Priority + { + get { return BackingStore?.Get("priority"); } + set { BackingStore?.Set("priority", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInCreateTodoItemRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInCreateTodoItemRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "description", n => { Description = n.GetStringValue(); } }, + { "durationInHours", n => { DurationInHours = n.GetLongValue(); } }, + { "priority", n => { Priority = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("description", Description); + writer.WriteLongValue("durationInHours", DurationInHours); + writer.WriteEnumValue("priority", Priority); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInPersonResponse.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInPersonResponse.cs new file mode 100644 index 0000000000..ab1156dd4a --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInPersonResponse.cs @@ -0,0 +1,76 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInPersonResponse : global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The displayName property + public string? DisplayName + { + get { return BackingStore?.Get("displayName"); } + set { BackingStore?.Set("displayName", value); } + } + + /// The firstName property + public string? FirstName + { + get { return BackingStore?.Get("firstName"); } + set { BackingStore?.Set("firstName", value); } + } + + /// The lastName property + public string? LastName + { + get { return BackingStore?.Get("lastName"); } + set { BackingStore?.Set("lastName", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInPersonResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInPersonResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "displayName", n => { DisplayName = n.GetStringValue(); } }, + { "firstName", n => { FirstName = n.GetStringValue(); } }, + { "lastName", n => { LastName = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("firstName", FirstName); + writer.WriteStringValue("lastName", LastName); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInResponse.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInResponse.cs new file mode 100644 index 0000000000..6ff4a6df92 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInResponse.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "people" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInPersonResponse(), + "tags" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInTagResponse(), + "todoItems" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInTodoItemResponse(), + _ => new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInTagResponse.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInTagResponse.cs new file mode 100644 index 0000000000..1c17475540 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInTagResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInTagResponse : global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInTagResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInTagResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInTodoItemResponse.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInTodoItemResponse.cs new file mode 100644 index 0000000000..e3d822bc8d --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInTodoItemResponse.cs @@ -0,0 +1,95 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInTodoItemResponse : global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The createdAt property + public DateTimeOffset? CreatedAt + { + get { return BackingStore?.Get("createdAt"); } + set { BackingStore?.Set("createdAt", value); } + } + + /// The description property + public string? Description + { + get { return BackingStore?.Get("description"); } + set { BackingStore?.Set("description", value); } + } + + /// The durationInHours property + public long? DurationInHours + { + get { return BackingStore?.Get("durationInHours"); } + set { BackingStore?.Set("durationInHours", value); } + } + + /// The modifiedAt property + public DateTimeOffset? ModifiedAt + { + get { return BackingStore?.Get("modifiedAt"); } + set { BackingStore?.Set("modifiedAt", value); } + } + + /// The priority property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemPriority? Priority + { + get { return BackingStore?.Get("priority"); } + set { BackingStore?.Set("priority", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInTodoItemResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInTodoItemResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "createdAt", n => { CreatedAt = n.GetDateTimeOffsetValue(); } }, + { "description", n => { Description = n.GetStringValue(); } }, + { "durationInHours", n => { DurationInHours = n.GetLongValue(); } }, + { "modifiedAt", n => { ModifiedAt = n.GetDateTimeOffsetValue(); } }, + { "priority", n => { Priority = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteDateTimeOffsetValue("createdAt", CreatedAt); + writer.WriteStringValue("description", Description); + writer.WriteLongValue("durationInHours", DurationInHours); + writer.WriteDateTimeOffsetValue("modifiedAt", ModifiedAt); + writer.WriteEnumValue("priority", Priority); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInUpdatePersonRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInUpdatePersonRequest.cs new file mode 100644 index 0000000000..eac162ccac --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInUpdatePersonRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdatePersonRequest : global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The firstName property + public string? FirstName + { + get { return BackingStore?.Get("firstName"); } + set { BackingStore?.Set("firstName", value); } + } + + /// The lastName property + public string? LastName + { + get { return BackingStore?.Get("lastName"); } + set { BackingStore?.Set("lastName", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInUpdatePersonRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInUpdatePersonRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "firstName", n => { FirstName = n.GetStringValue(); } }, + { "lastName", n => { LastName = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("firstName", FirstName); + writer.WriteStringValue("lastName", LastName); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInUpdateRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInUpdateRequest.cs new file mode 100644 index 0000000000..3da7558632 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInUpdateRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "people" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInUpdatePersonRequest(), + "tags" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInUpdateTagRequest(), + "todoItems" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInUpdateTodoItemRequest(), + _ => new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInUpdateTagRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInUpdateTagRequest.cs new file mode 100644 index 0000000000..4f09c54701 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInUpdateTagRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateTagRequest : global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInUpdateTagRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInUpdateTagRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInUpdateTodoItemRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInUpdateTodoItemRequest.cs new file mode 100644 index 0000000000..bac8e0a4d9 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/AttributesInUpdateTodoItemRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateTodoItemRequest : global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The description property + public string? Description + { + get { return BackingStore?.Get("description"); } + set { BackingStore?.Set("description", value); } + } + + /// The durationInHours property + public long? DurationInHours + { + get { return BackingStore?.Get("durationInHours"); } + set { BackingStore?.Set("durationInHours", value); } + } + + /// The priority property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemPriority? Priority + { + get { return BackingStore?.Get("priority"); } + set { BackingStore?.Set("priority", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInUpdateTodoItemRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInUpdateTodoItemRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "description", n => { Description = n.GetStringValue(); } }, + { "durationInHours", n => { DurationInHours = n.GetLongValue(); } }, + { "priority", n => { Priority = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("description", Description); + writer.WriteLongValue("durationInHours", DurationInHours); + writer.WriteEnumValue("priority", Priority); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/CreatePersonOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/CreatePersonOperation.cs new file mode 100644 index 0000000000..c3c532fe55 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/CreatePersonOperation.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreatePersonOperation : global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInCreatePersonRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.AddOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.CreatePersonOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.CreatePersonOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInCreatePersonRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/CreatePersonRequestDocument.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/CreatePersonRequestDocument.cs new file mode 100644 index 0000000000..506e9b2d18 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/CreatePersonRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreatePersonRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInCreatePersonRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreatePersonRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.CreatePersonRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.CreatePersonRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInCreatePersonRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/CreateTagOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/CreateTagOperation.cs new file mode 100644 index 0000000000..18304dc659 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/CreateTagOperation.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateTagOperation : global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInCreateTagRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.AddOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.CreateTagOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.CreateTagOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInCreateTagRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/CreateTagRequestDocument.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/CreateTagRequestDocument.cs new file mode 100644 index 0000000000..f339b44870 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/CreateTagRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateTagRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInCreateTagRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateTagRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.CreateTagRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.CreateTagRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInCreateTagRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/CreateTodoItemOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/CreateTodoItemOperation.cs new file mode 100644 index 0000000000..a879dba99a --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/CreateTodoItemOperation.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateTodoItemOperation : global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInCreateTodoItemRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.AddOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.CreateTodoItemOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.CreateTodoItemOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInCreateTodoItemRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/CreateTodoItemRequestDocument.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/CreateTodoItemRequestDocument.cs new file mode 100644 index 0000000000..d3857f3ef4 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/CreateTodoItemRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateTodoItemRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInCreateTodoItemRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateTodoItemRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.CreateTodoItemRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.CreateTodoItemRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInCreateTodoItemRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInCreatePersonRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInCreatePersonRequest.cs new file mode 100644 index 0000000000..a73695584b --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInCreatePersonRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreatePersonRequest : global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInCreatePersonRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInCreatePersonRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInCreatePersonRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInCreatePersonRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInCreatePersonRequest.CreateFromDiscriminatorValue); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInCreatePersonRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInCreateTagRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInCreateTagRequest.cs new file mode 100644 index 0000000000..705018cfa6 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInCreateTagRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateTagRequest : global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInCreateTagRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInCreateTagRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInCreateTagRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInCreateTagRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInCreateTagRequest.CreateFromDiscriminatorValue); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInCreateTagRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInCreateTodoItemRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInCreateTodoItemRequest.cs new file mode 100644 index 0000000000..e1493f92ca --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInCreateTodoItemRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateTodoItemRequest : global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInCreateTodoItemRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInCreateTodoItemRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInCreateTodoItemRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInCreateTodoItemRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInCreateTodoItemRequest.CreateFromDiscriminatorValue); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInCreateTodoItemRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInPersonResponse.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInPersonResponse.cs new file mode 100644 index 0000000000..102783642e --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInPersonResponse.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInPersonResponse : global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInPersonResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInPersonResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInPersonResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInPersonResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInPersonResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInPersonResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInTagResponse.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInTagResponse.cs new file mode 100644 index 0000000000..d32e8dd080 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInTagResponse.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInTagResponse : global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInTagResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInTagResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInTagResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInTagResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInTagResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInTagResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInTodoItemResponse.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInTodoItemResponse.cs new file mode 100644 index 0000000000..abe7290e36 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInTodoItemResponse.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInTodoItemResponse : global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInTodoItemResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInTodoItemResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInTodoItemResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInTodoItemResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInTodoItemResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInTodoItemResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInUpdatePersonRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInUpdatePersonRequest.cs new file mode 100644 index 0000000000..4cc76e39b0 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInUpdatePersonRequest.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdatePersonRequest : global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInUpdatePersonRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInUpdatePersonRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInUpdatePersonRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInUpdatePersonRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInUpdatePersonRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInUpdatePersonRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInUpdateTagRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInUpdateTagRequest.cs new file mode 100644 index 0000000000..67e8f056d0 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInUpdateTagRequest.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateTagRequest : global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInUpdateTagRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInUpdateTagRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInUpdateTagRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInUpdateTagRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInUpdateTagRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInUpdateTagRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInUpdateTodoItemRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInUpdateTodoItemRequest.cs new file mode 100644 index 0000000000..f3500e1884 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DataInUpdateTodoItemRequest.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateTodoItemRequest : global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInUpdateTodoItemRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInUpdateTodoItemRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInUpdateTodoItemRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInUpdateTodoItemRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.AttributesInUpdateTodoItemRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInUpdateTodoItemRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DeletePersonOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DeletePersonOperation.cs new file mode 100644 index 0000000000..a935cf7f39 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DeletePersonOperation.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DeletePersonOperation : global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The op property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.RemoveOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInRequest? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.DeletePersonOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.DeletePersonOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DeleteTagOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DeleteTagOperation.cs new file mode 100644 index 0000000000..2fc9ab07e4 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DeleteTagOperation.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DeleteTagOperation : global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The op property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.RemoveOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TagIdentifierInRequest? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.DeleteTagOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.DeleteTagOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.TagIdentifierInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DeleteTodoItemOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DeleteTodoItemOperation.cs new file mode 100644 index 0000000000..4078148c04 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/DeleteTodoItemOperation.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DeleteTodoItemOperation : global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The op property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.RemoveOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierInRequest? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.DeleteTodoItemOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.DeleteTodoItemOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ErrorLinks.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ErrorLinks.cs new file mode 100644 index 0000000000..14988baa15 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ErrorLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// The about property + public string? About + { + get { return BackingStore?.Get("about"); } + set { BackingStore?.Set("about", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The type property + public string? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "about", n => { About = n.GetStringValue(); } }, + { "type", n => { Type = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("about", About); + writer.WriteStringValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ErrorObject.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ErrorObject.cs new file mode 100644 index 0000000000..54b277a3e4 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ErrorObject.cs @@ -0,0 +1,133 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorObject : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The code property + public string? Code + { + get { return BackingStore?.Get("code"); } + set { BackingStore?.Set("code", value); } + } + + /// The detail property + public string? Detail + { + get { return BackingStore?.Get("detail"); } + set { BackingStore?.Set("detail", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The source property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorSource? Source + { + get { return BackingStore?.Get("source"); } + set { BackingStore?.Set("source", value); } + } + + /// The status property + public string? Status + { + get { return BackingStore?.Get("status"); } + set { BackingStore?.Set("status", value); } + } + + /// The title property + public string? Title + { + get { return BackingStore?.Get("title"); } + set { BackingStore?.Set("title", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorObject() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorObject CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorObject(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "code", n => { Code = n.GetStringValue(); } }, + { "detail", n => { Detail = n.GetStringValue(); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "source", n => { Source = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorSource.CreateFromDiscriminatorValue); } }, + { "status", n => { Status = n.GetStringValue(); } }, + { "title", n => { Title = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("code", Code); + writer.WriteStringValue("detail", Detail); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + writer.WriteObjectValue("source", Source); + writer.WriteStringValue("status", Status); + writer.WriteStringValue("title", Title); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ErrorResponseDocument.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ErrorResponseDocument.cs new file mode 100644 index 0000000000..fa3d55ee54 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ErrorResponseDocument.cs @@ -0,0 +1,92 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorResponseDocument : ApiException, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The errors property + public List? Errors + { + get { return BackingStore?.Get?>("errors"); } + set { BackingStore?.Set("errors", value); } + } + + /// The links property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The primary error message. + public override string Message { get => base.Message; } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "errors", n => { Errors = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorObject.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("errors", Errors); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ErrorSource.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ErrorSource.cs new file mode 100644 index 0000000000..2c2b7e45cc --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ErrorSource.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorSource : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The header property + public string? Header + { + get { return BackingStore?.Get("header"); } + set { BackingStore?.Set("header", value); } + } + + /// The parameter property + public string? Parameter + { + get { return BackingStore?.Get("parameter"); } + set { BackingStore?.Set("parameter", value); } + } + + /// The pointer property + public string? Pointer + { + get { return BackingStore?.Get("pointer"); } + set { BackingStore?.Set("pointer", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorSource() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorSource CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorSource(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "header", n => { Header = n.GetStringValue(); } }, + { "parameter", n => { Parameter = n.GetStringValue(); } }, + { "pointer", n => { Pointer = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("header", Header); + writer.WriteStringValue("parameter", Parameter); + writer.WriteStringValue("pointer", Pointer); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ErrorTopLevelLinks.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ErrorTopLevelLinks.cs new file mode 100644 index 0000000000..bf238e2e6e --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ErrorTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.ErrorTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/IdentifierInRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/IdentifierInRequest.cs new file mode 100644 index 0000000000..a997c6e0bf --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/IdentifierInRequest.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class IdentifierInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public IdentifierInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.IdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "people" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInRequest(), + "tags" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.TagIdentifierInRequest(), + "todoItems" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierInRequest(), + _ => new global::OpenApiKiotaClientExample.GeneratedCode.Models.IdentifierInRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/Meta.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/Meta.cs new file mode 100644 index 0000000000..1e5f665402 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/Meta.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class Meta : IAdditionalDataHolder, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + public IDictionary AdditionalData + { + get { return BackingStore.Get>("AdditionalData") ?? new Dictionary(); } + set { BackingStore.Set("AdditionalData", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// + /// Instantiates a new and sets the default values. + /// + public Meta() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + AdditionalData = new Dictionary(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteAdditionalData(AdditionalData); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/NullablePersonIdentifierResponseDocument.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/NullablePersonIdentifierResponseDocument.cs new file mode 100644 index 0000000000..245fb8a3bb --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/NullablePersonIdentifierResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NullablePersonIdentifierResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceIdentifierTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NullablePersonIdentifierResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.NullablePersonIdentifierResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.NullablePersonIdentifierResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceIdentifierTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/NullableSecondaryPersonResponseDocument.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/NullableSecondaryPersonResponseDocument.cs new file mode 100644 index 0000000000..f3a621d45c --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/NullableSecondaryPersonResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NullableSecondaryPersonResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInPersonResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NullableSecondaryPersonResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.NullableSecondaryPersonResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.NullableSecondaryPersonResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInPersonResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/NullableToOnePersonInRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/NullableToOnePersonInRequest.cs new file mode 100644 index 0000000000..5eab19e48b --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/NullableToOnePersonInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NullableToOnePersonInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NullableToOnePersonInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.NullableToOnePersonInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.NullableToOnePersonInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/NullableToOnePersonInResponse.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/NullableToOnePersonInResponse.cs new file mode 100644 index 0000000000..0de8cf3d6e --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/NullableToOnePersonInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NullableToOnePersonInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NullableToOnePersonInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.NullableToOnePersonInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.NullableToOnePersonInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/OperationsRequestDocument.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/OperationsRequestDocument.cs new file mode 100644 index 0000000000..3bd1932eb1 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/OperationsRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class OperationsRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// The atomicOperations property + public List? AtomicOperations + { + get { return BackingStore?.Get?>("atomic:operations"); } + set { BackingStore?.Set("atomic:operations", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public OperationsRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.OperationsRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.OperationsRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "atomic:operations", n => { AtomicOperations = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("atomic:operations", AtomicOperations); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/OperationsResponseDocument.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/OperationsResponseDocument.cs new file mode 100644 index 0000000000..1c9588a0c5 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/OperationsResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class OperationsResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// The atomicResults property + public List? AtomicResults + { + get { return BackingStore?.Get?>("atomic:results"); } + set { BackingStore?.Set("atomic:results", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The links property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public OperationsResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.OperationsResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.OperationsResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "atomic:results", n => { AtomicResults = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicResult.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("atomic:results", AtomicResults); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonAssignedTodoItemsRelationshipIdentifier.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonAssignedTodoItemsRelationshipIdentifier.cs new file mode 100644 index 0000000000..e4b6d93b90 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonAssignedTodoItemsRelationshipIdentifier.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PersonAssignedTodoItemsRelationshipIdentifier : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationship property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonAssignedTodoItemsRelationshipName? Relationship + { + get { return BackingStore?.Get("relationship"); } + set { BackingStore?.Set("relationship", value); } + } + + /// The type property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PersonAssignedTodoItemsRelationshipIdentifier() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonAssignedTodoItemsRelationshipIdentifier CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonAssignedTodoItemsRelationshipIdentifier(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationship", n => { Relationship = n.GetEnumValue(); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteEnumValue("relationship", Relationship); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonAssignedTodoItemsRelationshipName.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonAssignedTodoItemsRelationshipName.cs new file mode 100644 index 0000000000..bef09282ad --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonAssignedTodoItemsRelationshipName.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum PersonAssignedTodoItemsRelationshipName + #pragma warning restore CS1591 + { + [EnumMember(Value = "assignedTodoItems")] + #pragma warning disable CS1591 + AssignedTodoItems, + #pragma warning restore CS1591 + } +} diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonCollectionResponseDocument.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonCollectionResponseDocument.cs new file mode 100644 index 0000000000..3b92c217c9 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PersonCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PersonCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInPersonResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonIdentifierInRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonIdentifierInRequest.cs new file mode 100644 index 0000000000..45aadb8951 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonIdentifierInRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PersonIdentifierInRequest : global::OpenApiKiotaClientExample.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonIdentifierInResponse.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonIdentifierInResponse.cs new file mode 100644 index 0000000000..7c051da21f --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonIdentifierInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PersonIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PersonIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonIdentifierResponseDocument.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonIdentifierResponseDocument.cs new file mode 100644 index 0000000000..a7ca24727d --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonIdentifierResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PersonIdentifierResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceIdentifierTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PersonIdentifierResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceIdentifierTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonOwnedTodoItemsRelationshipIdentifier.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonOwnedTodoItemsRelationshipIdentifier.cs new file mode 100644 index 0000000000..62e03c01f8 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonOwnedTodoItemsRelationshipIdentifier.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PersonOwnedTodoItemsRelationshipIdentifier : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationship property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonOwnedTodoItemsRelationshipName? Relationship + { + get { return BackingStore?.Get("relationship"); } + set { BackingStore?.Set("relationship", value); } + } + + /// The type property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PersonOwnedTodoItemsRelationshipIdentifier() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonOwnedTodoItemsRelationshipIdentifier CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonOwnedTodoItemsRelationshipIdentifier(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationship", n => { Relationship = n.GetEnumValue(); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteEnumValue("relationship", Relationship); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonOwnedTodoItemsRelationshipName.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonOwnedTodoItemsRelationshipName.cs new file mode 100644 index 0000000000..5c7c841a13 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonOwnedTodoItemsRelationshipName.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum PersonOwnedTodoItemsRelationshipName + #pragma warning restore CS1591 + { + [EnumMember(Value = "ownedTodoItems")] + #pragma warning disable CS1591 + OwnedTodoItems, + #pragma warning restore CS1591 + } +} diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonResourceType.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonResourceType.cs new file mode 100644 index 0000000000..309e481056 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PersonResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum PersonResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "people")] + #pragma warning disable CS1591 + People, + #pragma warning restore CS1591 + } +} diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PrimaryPersonResponseDocument.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PrimaryPersonResponseDocument.cs new file mode 100644 index 0000000000..769819ff5d --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PrimaryPersonResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryPersonResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInPersonResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryPersonResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.PrimaryPersonResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.PrimaryPersonResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInPersonResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PrimaryTagResponseDocument.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PrimaryTagResponseDocument.cs new file mode 100644 index 0000000000..56faf94dec --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PrimaryTagResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryTagResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInTagResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryTagResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.PrimaryTagResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.PrimaryTagResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInTagResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PrimaryTodoItemResponseDocument.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PrimaryTodoItemResponseDocument.cs new file mode 100644 index 0000000000..2aefc28121 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/PrimaryTodoItemResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryTodoItemResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInTodoItemResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryTodoItemResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.PrimaryTodoItemResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.PrimaryTodoItemResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInTodoItemResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipLinks.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipLinks.cs new file mode 100644 index 0000000000..1dfc44ee8d --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInCreatePersonRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInCreatePersonRequest.cs new file mode 100644 index 0000000000..a7c1dc9803 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInCreatePersonRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreatePersonRequest : global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The assignedTodoItems property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest? AssignedTodoItems + { + get { return BackingStore?.Get("assignedTodoItems"); } + set { BackingStore?.Set("assignedTodoItems", value); } + } + + /// The ownedTodoItems property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest? OwnedTodoItems + { + get { return BackingStore?.Get("ownedTodoItems"); } + set { BackingStore?.Set("ownedTodoItems", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInCreatePersonRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInCreatePersonRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "assignedTodoItems", n => { AssignedTodoItems = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest.CreateFromDiscriminatorValue); } }, + { "ownedTodoItems", n => { OwnedTodoItems = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("assignedTodoItems", AssignedTodoItems); + writer.WriteObjectValue("ownedTodoItems", OwnedTodoItems); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInCreateRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInCreateRequest.cs new file mode 100644 index 0000000000..c9c8d2247d --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInCreateRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "people" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInCreatePersonRequest(), + "tags" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInCreateTagRequest(), + "todoItems" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInCreateTodoItemRequest(), + _ => new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInCreateTagRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInCreateTagRequest.cs new file mode 100644 index 0000000000..6faaa2cb56 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInCreateTagRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateTagRequest : global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The todoItems property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest? TodoItems + { + get { return BackingStore?.Get("todoItems"); } + set { BackingStore?.Set("todoItems", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInCreateTagRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInCreateTagRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "todoItems", n => { TodoItems = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("todoItems", TodoItems); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInCreateTodoItemRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInCreateTodoItemRequest.cs new file mode 100644 index 0000000000..0a8e32873b --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInCreateTodoItemRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateTodoItemRequest : global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The assignee property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.NullableToOnePersonInRequest? Assignee + { + get { return BackingStore?.Get("assignee"); } + set { BackingStore?.Set("assignee", value); } + } + + /// The owner property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ToOnePersonInRequest? Owner + { + get { return BackingStore?.Get("owner"); } + set { BackingStore?.Set("owner", value); } + } + + /// The tags property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTagInRequest? Tags + { + get { return BackingStore?.Get("tags"); } + set { BackingStore?.Set("tags", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInCreateTodoItemRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInCreateTodoItemRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "assignee", n => { Assignee = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.NullableToOnePersonInRequest.CreateFromDiscriminatorValue); } }, + { "owner", n => { Owner = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToOnePersonInRequest.CreateFromDiscriminatorValue); } }, + { "tags", n => { Tags = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTagInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("assignee", Assignee); + writer.WriteObjectValue("owner", Owner); + writer.WriteObjectValue("tags", Tags); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInPersonResponse.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInPersonResponse.cs new file mode 100644 index 0000000000..700c9b301a --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInPersonResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInPersonResponse : global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// The assignedTodoItems property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInResponse? AssignedTodoItems + { + get { return BackingStore?.Get("assignedTodoItems"); } + set { BackingStore?.Set("assignedTodoItems", value); } + } + + /// The ownedTodoItems property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInResponse? OwnedTodoItems + { + get { return BackingStore?.Get("ownedTodoItems"); } + set { BackingStore?.Set("ownedTodoItems", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInPersonResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInPersonResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "assignedTodoItems", n => { AssignedTodoItems = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInResponse.CreateFromDiscriminatorValue); } }, + { "ownedTodoItems", n => { OwnedTodoItems = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("assignedTodoItems", AssignedTodoItems); + writer.WriteObjectValue("ownedTodoItems", OwnedTodoItems); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInResponse.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInResponse.cs new file mode 100644 index 0000000000..037808aa1f --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInResponse.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "people" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInPersonResponse(), + "tags" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInTagResponse(), + "todoItems" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInTodoItemResponse(), + _ => new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInTagResponse.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInTagResponse.cs new file mode 100644 index 0000000000..eb854e08d8 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInTagResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInTagResponse : global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// The todoItems property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInResponse? TodoItems + { + get { return BackingStore?.Get("todoItems"); } + set { BackingStore?.Set("todoItems", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInTagResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInTagResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "todoItems", n => { TodoItems = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("todoItems", TodoItems); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInTodoItemResponse.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInTodoItemResponse.cs new file mode 100644 index 0000000000..56e9402ada --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInTodoItemResponse.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInTodoItemResponse : global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// The assignee property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.NullableToOnePersonInResponse? Assignee + { + get { return BackingStore?.Get("assignee"); } + set { BackingStore?.Set("assignee", value); } + } + + /// The owner property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ToOnePersonInResponse? Owner + { + get { return BackingStore?.Get("owner"); } + set { BackingStore?.Set("owner", value); } + } + + /// The tags property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTagInResponse? Tags + { + get { return BackingStore?.Get("tags"); } + set { BackingStore?.Set("tags", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInTodoItemResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInTodoItemResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "assignee", n => { Assignee = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.NullableToOnePersonInResponse.CreateFromDiscriminatorValue); } }, + { "owner", n => { Owner = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToOnePersonInResponse.CreateFromDiscriminatorValue); } }, + { "tags", n => { Tags = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTagInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("assignee", Assignee); + writer.WriteObjectValue("owner", Owner); + writer.WriteObjectValue("tags", Tags); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInUpdatePersonRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInUpdatePersonRequest.cs new file mode 100644 index 0000000000..ee9185a310 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInUpdatePersonRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdatePersonRequest : global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The assignedTodoItems property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest? AssignedTodoItems + { + get { return BackingStore?.Get("assignedTodoItems"); } + set { BackingStore?.Set("assignedTodoItems", value); } + } + + /// The ownedTodoItems property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest? OwnedTodoItems + { + get { return BackingStore?.Get("ownedTodoItems"); } + set { BackingStore?.Set("ownedTodoItems", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInUpdatePersonRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInUpdatePersonRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "assignedTodoItems", n => { AssignedTodoItems = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest.CreateFromDiscriminatorValue); } }, + { "ownedTodoItems", n => { OwnedTodoItems = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("assignedTodoItems", AssignedTodoItems); + writer.WriteObjectValue("ownedTodoItems", OwnedTodoItems); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInUpdateRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInUpdateRequest.cs new file mode 100644 index 0000000000..13621d8e84 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInUpdateRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "people" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInUpdatePersonRequest(), + "tags" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInUpdateTagRequest(), + "todoItems" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInUpdateTodoItemRequest(), + _ => new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInUpdateTagRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInUpdateTagRequest.cs new file mode 100644 index 0000000000..87a99d727d --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInUpdateTagRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateTagRequest : global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The todoItems property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest? TodoItems + { + get { return BackingStore?.Get("todoItems"); } + set { BackingStore?.Set("todoItems", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInUpdateTagRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInUpdateTagRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "todoItems", n => { TodoItems = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("todoItems", TodoItems); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInUpdateTodoItemRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInUpdateTodoItemRequest.cs new file mode 100644 index 0000000000..0503466973 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RelationshipsInUpdateTodoItemRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateTodoItemRequest : global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The assignee property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.NullableToOnePersonInRequest? Assignee + { + get { return BackingStore?.Get("assignee"); } + set { BackingStore?.Set("assignee", value); } + } + + /// The owner property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ToOnePersonInRequest? Owner + { + get { return BackingStore?.Get("owner"); } + set { BackingStore?.Set("owner", value); } + } + + /// The tags property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTagInRequest? Tags + { + get { return BackingStore?.Get("tags"); } + set { BackingStore?.Set("tags", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInUpdateTodoItemRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipsInUpdateTodoItemRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "assignee", n => { Assignee = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.NullableToOnePersonInRequest.CreateFromDiscriminatorValue); } }, + { "owner", n => { Owner = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToOnePersonInRequest.CreateFromDiscriminatorValue); } }, + { "tags", n => { Tags = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTagInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("assignee", Assignee); + writer.WriteObjectValue("owner", Owner); + writer.WriteObjectValue("tags", Tags); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RemoveFromPersonAssignedTodoItemsRelationshipOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RemoveFromPersonAssignedTodoItemsRelationshipOperation.cs new file mode 100644 index 0000000000..a1723493b7 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RemoveFromPersonAssignedTodoItemsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RemoveFromPersonAssignedTodoItemsRelationshipOperation : global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.RemoveOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonAssignedTodoItemsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.RemoveFromPersonAssignedTodoItemsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.RemoveFromPersonAssignedTodoItemsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonAssignedTodoItemsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RemoveFromPersonOwnedTodoItemsRelationshipOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RemoveFromPersonOwnedTodoItemsRelationshipOperation.cs new file mode 100644 index 0000000000..d382626143 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RemoveFromPersonOwnedTodoItemsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RemoveFromPersonOwnedTodoItemsRelationshipOperation : global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.RemoveOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonOwnedTodoItemsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.RemoveFromPersonOwnedTodoItemsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.RemoveFromPersonOwnedTodoItemsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonOwnedTodoItemsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RemoveFromTagTodoItemsRelationshipOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RemoveFromTagTodoItemsRelationshipOperation.cs new file mode 100644 index 0000000000..dac043b40f --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RemoveFromTagTodoItemsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RemoveFromTagTodoItemsRelationshipOperation : global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.RemoveOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TagTodoItemsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.RemoveFromTagTodoItemsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.RemoveFromTagTodoItemsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.TagTodoItemsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RemoveFromTodoItemTagsRelationshipOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RemoveFromTodoItemTagsRelationshipOperation.cs new file mode 100644 index 0000000000..728838ac24 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RemoveFromTodoItemTagsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RemoveFromTodoItemTagsRelationshipOperation : global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.RemoveOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemTagsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.RemoveFromTodoItemTagsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.RemoveFromTodoItemTagsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.TagIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemTagsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RemoveOperationCode.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RemoveOperationCode.cs new file mode 100644 index 0000000000..e49087bf47 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/RemoveOperationCode.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum RemoveOperationCode + #pragma warning restore CS1591 + { + [EnumMember(Value = "remove")] + #pragma warning disable CS1591 + Remove, + #pragma warning restore CS1591 + } +} diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceCollectionTopLevelLinks.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceCollectionTopLevelLinks.cs new file mode 100644 index 0000000000..2eff9f8e0e --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceCollectionTopLevelLinks.cs @@ -0,0 +1,115 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceCollectionTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The first property + public string? First + { + get { return BackingStore?.Get("first"); } + set { BackingStore?.Set("first", value); } + } + + /// The last property + public string? Last + { + get { return BackingStore?.Get("last"); } + set { BackingStore?.Set("last", value); } + } + + /// The next property + public string? Next + { + get { return BackingStore?.Get("next"); } + set { BackingStore?.Set("next", value); } + } + + /// The prev property + public string? Prev + { + get { return BackingStore?.Get("prev"); } + set { BackingStore?.Set("prev", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceCollectionTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceCollectionTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceCollectionTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "first", n => { First = n.GetStringValue(); } }, + { "last", n => { Last = n.GetStringValue(); } }, + { "next", n => { Next = n.GetStringValue(); } }, + { "prev", n => { Prev = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("first", First); + writer.WriteStringValue("last", Last); + writer.WriteStringValue("next", Next); + writer.WriteStringValue("prev", Prev); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs new file mode 100644 index 0000000000..5c45ab0eb8 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs @@ -0,0 +1,124 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceIdentifierCollectionTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The first property + public string? First + { + get { return BackingStore?.Get("first"); } + set { BackingStore?.Set("first", value); } + } + + /// The last property + public string? Last + { + get { return BackingStore?.Get("last"); } + set { BackingStore?.Set("last", value); } + } + + /// The next property + public string? Next + { + get { return BackingStore?.Get("next"); } + set { BackingStore?.Set("next", value); } + } + + /// The prev property + public string? Prev + { + get { return BackingStore?.Get("prev"); } + set { BackingStore?.Set("prev", value); } + } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceIdentifierCollectionTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "first", n => { First = n.GetStringValue(); } }, + { "last", n => { Last = n.GetStringValue(); } }, + { "next", n => { Next = n.GetStringValue(); } }, + { "prev", n => { Prev = n.GetStringValue(); } }, + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("first", First); + writer.WriteStringValue("last", Last); + writer.WriteStringValue("next", Next); + writer.WriteStringValue("prev", Prev); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceIdentifierTopLevelLinks.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceIdentifierTopLevelLinks.cs new file mode 100644 index 0000000000..853e4af142 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceIdentifierTopLevelLinks.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceIdentifierTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceIdentifierTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceIdentifierTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceIdentifierTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceInCreateRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceInCreateRequest.cs new file mode 100644 index 0000000000..091cfb0a93 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceInCreateRequest.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "people" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInCreatePersonRequest(), + "tags" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInCreateTagRequest(), + "todoItems" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInCreateTodoItemRequest(), + _ => new global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceInResponse.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceInResponse.cs new file mode 100644 index 0000000000..b5417c7dd0 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceInResponse.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "people" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInPersonResponse(), + "tags" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInTagResponse(), + "todoItems" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInTodoItemResponse(), + _ => new global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceInUpdateRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceInUpdateRequest.cs new file mode 100644 index 0000000000..f59c44514e --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceInUpdateRequest.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "people" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInUpdatePersonRequest(), + "tags" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInUpdateTagRequest(), + "todoItems" => new global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInUpdateTodoItemRequest(), + _ => new global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceLinks.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceLinks.cs new file mode 100644 index 0000000000..e0b061e6b0 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceLinks.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceTopLevelLinks.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceTopLevelLinks.cs new file mode 100644 index 0000000000..1f2666f23d --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceType.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceType.cs new file mode 100644 index 0000000000..0fa83203d6 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ResourceType.cs @@ -0,0 +1,26 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum ResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "people")] + #pragma warning disable CS1591 + People, + #pragma warning restore CS1591 + [EnumMember(Value = "tags")] + #pragma warning disable CS1591 + Tags, + #pragma warning restore CS1591 + [EnumMember(Value = "todoItems")] + #pragma warning disable CS1591 + TodoItems, + #pragma warning restore CS1591 + } +} diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/SecondaryPersonResponseDocument.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/SecondaryPersonResponseDocument.cs new file mode 100644 index 0000000000..2ca28ffaba --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/SecondaryPersonResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class SecondaryPersonResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInPersonResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public SecondaryPersonResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.SecondaryPersonResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.SecondaryPersonResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInPersonResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TagCollectionResponseDocument.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TagCollectionResponseDocument.cs new file mode 100644 index 0000000000..8a8212126b --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TagCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class TagCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public TagCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.TagCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.TagCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInTagResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TagIdentifierCollectionResponseDocument.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TagIdentifierCollectionResponseDocument.cs new file mode 100644 index 0000000000..30ef21fd5a --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TagIdentifierCollectionResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class TagIdentifierCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public TagIdentifierCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.TagIdentifierCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.TagIdentifierCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.TagIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TagIdentifierInRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TagIdentifierInRequest.cs new file mode 100644 index 0000000000..b1fa1ae9ea --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TagIdentifierInRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class TagIdentifierInRequest : global::OpenApiKiotaClientExample.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.TagIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.TagIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TagIdentifierInResponse.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TagIdentifierInResponse.cs new file mode 100644 index 0000000000..6da97abc35 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TagIdentifierInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class TagIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TagResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public TagIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.TagIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.TagIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TagResourceType.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TagResourceType.cs new file mode 100644 index 0000000000..5cc9335c56 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TagResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum TagResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "tags")] + #pragma warning disable CS1591 + Tags, + #pragma warning restore CS1591 + } +} diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TagTodoItemsRelationshipIdentifier.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TagTodoItemsRelationshipIdentifier.cs new file mode 100644 index 0000000000..1575de9edd --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TagTodoItemsRelationshipIdentifier.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class TagTodoItemsRelationshipIdentifier : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationship property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TagTodoItemsRelationshipName? Relationship + { + get { return BackingStore?.Get("relationship"); } + set { BackingStore?.Set("relationship", value); } + } + + /// The type property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TagResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public TagTodoItemsRelationshipIdentifier() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.TagTodoItemsRelationshipIdentifier CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.TagTodoItemsRelationshipIdentifier(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationship", n => { Relationship = n.GetEnumValue(); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteEnumValue("relationship", Relationship); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TagTodoItemsRelationshipName.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TagTodoItemsRelationshipName.cs new file mode 100644 index 0000000000..688ef7a666 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TagTodoItemsRelationshipName.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum TagTodoItemsRelationshipName + #pragma warning restore CS1591 + { + [EnumMember(Value = "todoItems")] + #pragma warning disable CS1591 + TodoItems, + #pragma warning restore CS1591 + } +} diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ToManyTagInRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ToManyTagInRequest.cs new file mode 100644 index 0000000000..f4b01be848 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ToManyTagInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyTagInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyTagInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTagInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTagInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.TagIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ToManyTagInResponse.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ToManyTagInResponse.cs new file mode 100644 index 0000000000..499498c582 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ToManyTagInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyTagInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyTagInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTagInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTagInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.TagIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ToManyTodoItemInRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ToManyTodoItemInRequest.cs new file mode 100644 index 0000000000..4278fbdcf1 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ToManyTodoItemInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyTodoItemInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyTodoItemInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ToManyTodoItemInResponse.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ToManyTodoItemInResponse.cs new file mode 100644 index 0000000000..cdb6ae027d --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ToManyTodoItemInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyTodoItemInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyTodoItemInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.ToManyTodoItemInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ToOnePersonInRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ToOnePersonInRequest.cs new file mode 100644 index 0000000000..054d054a47 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ToOnePersonInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToOnePersonInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToOnePersonInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.ToOnePersonInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.ToOnePersonInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ToOnePersonInResponse.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ToOnePersonInResponse.cs new file mode 100644 index 0000000000..7223b715cb --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/ToOnePersonInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToOnePersonInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToOnePersonInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.ToOnePersonInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.ToOnePersonInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemAssigneeRelationshipIdentifier.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemAssigneeRelationshipIdentifier.cs new file mode 100644 index 0000000000..b3776ea784 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemAssigneeRelationshipIdentifier.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class TodoItemAssigneeRelationshipIdentifier : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationship property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemAssigneeRelationshipName? Relationship + { + get { return BackingStore?.Get("relationship"); } + set { BackingStore?.Set("relationship", value); } + } + + /// The type property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public TodoItemAssigneeRelationshipIdentifier() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemAssigneeRelationshipIdentifier CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemAssigneeRelationshipIdentifier(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationship", n => { Relationship = n.GetEnumValue(); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteEnumValue("relationship", Relationship); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemAssigneeRelationshipName.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemAssigneeRelationshipName.cs new file mode 100644 index 0000000000..ab067713d3 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemAssigneeRelationshipName.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum TodoItemAssigneeRelationshipName + #pragma warning restore CS1591 + { + [EnumMember(Value = "assignee")] + #pragma warning disable CS1591 + Assignee, + #pragma warning restore CS1591 + } +} diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemCollectionResponseDocument.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemCollectionResponseDocument.cs new file mode 100644 index 0000000000..39924b4e0c --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class TodoItemCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public TodoItemCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInTodoItemResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemIdentifierCollectionResponseDocument.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemIdentifierCollectionResponseDocument.cs new file mode 100644 index 0000000000..07f5dc0740 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemIdentifierCollectionResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class TodoItemIdentifierCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public TodoItemIdentifierCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemIdentifierInRequest.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemIdentifierInRequest.cs new file mode 100644 index 0000000000..625c96abfe --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemIdentifierInRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class TodoItemIdentifierInRequest : global::OpenApiKiotaClientExample.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemIdentifierInResponse.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemIdentifierInResponse.cs new file mode 100644 index 0000000000..77e66a4932 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemIdentifierInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class TodoItemIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public TodoItemIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemOwnerRelationshipIdentifier.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemOwnerRelationshipIdentifier.cs new file mode 100644 index 0000000000..9280347acf --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemOwnerRelationshipIdentifier.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class TodoItemOwnerRelationshipIdentifier : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationship property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemOwnerRelationshipName? Relationship + { + get { return BackingStore?.Get("relationship"); } + set { BackingStore?.Set("relationship", value); } + } + + /// The type property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public TodoItemOwnerRelationshipIdentifier() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemOwnerRelationshipIdentifier CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemOwnerRelationshipIdentifier(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationship", n => { Relationship = n.GetEnumValue(); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteEnumValue("relationship", Relationship); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemOwnerRelationshipName.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemOwnerRelationshipName.cs new file mode 100644 index 0000000000..9b93bc5cf2 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemOwnerRelationshipName.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum TodoItemOwnerRelationshipName + #pragma warning restore CS1591 + { + [EnumMember(Value = "owner")] + #pragma warning disable CS1591 + Owner, + #pragma warning restore CS1591 + } +} diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemPriority.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemPriority.cs new file mode 100644 index 0000000000..1736350c36 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemPriority.cs @@ -0,0 +1,26 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum TodoItemPriority + #pragma warning restore CS1591 + { + [EnumMember(Value = "High")] + #pragma warning disable CS1591 + High, + #pragma warning restore CS1591 + [EnumMember(Value = "Medium")] + #pragma warning disable CS1591 + Medium, + #pragma warning restore CS1591 + [EnumMember(Value = "Low")] + #pragma warning disable CS1591 + Low, + #pragma warning restore CS1591 + } +} diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemResourceType.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemResourceType.cs new file mode 100644 index 0000000000..3f6583ffa8 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum TodoItemResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "todoItems")] + #pragma warning disable CS1591 + TodoItems, + #pragma warning restore CS1591 + } +} diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemTagsRelationshipIdentifier.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemTagsRelationshipIdentifier.cs new file mode 100644 index 0000000000..8f60910bf9 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemTagsRelationshipIdentifier.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class TodoItemTagsRelationshipIdentifier : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationship property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemTagsRelationshipName? Relationship + { + get { return BackingStore?.Get("relationship"); } + set { BackingStore?.Set("relationship", value); } + } + + /// The type property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public TodoItemTagsRelationshipIdentifier() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemTagsRelationshipIdentifier CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemTagsRelationshipIdentifier(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationship", n => { Relationship = n.GetEnumValue(); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteEnumValue("relationship", Relationship); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemTagsRelationshipName.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemTagsRelationshipName.cs new file mode 100644 index 0000000000..e5c0a6aecd --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/TodoItemTagsRelationshipName.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum TodoItemTagsRelationshipName + #pragma warning restore CS1591 + { + [EnumMember(Value = "tags")] + #pragma warning disable CS1591 + Tags, + #pragma warning restore CS1591 + } +} diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateOperationCode.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateOperationCode.cs new file mode 100644 index 0000000000..615d734065 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateOperationCode.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum UpdateOperationCode + #pragma warning restore CS1591 + { + [EnumMember(Value = "update")] + #pragma warning disable CS1591 + Update, + #pragma warning restore CS1591 + } +} diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdatePersonAssignedTodoItemsRelationshipOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdatePersonAssignedTodoItemsRelationshipOperation.cs new file mode 100644 index 0000000000..4e49dae8ab --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdatePersonAssignedTodoItemsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdatePersonAssignedTodoItemsRelationshipOperation : global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonAssignedTodoItemsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdatePersonAssignedTodoItemsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdatePersonAssignedTodoItemsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonAssignedTodoItemsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdatePersonOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdatePersonOperation.cs new file mode 100644 index 0000000000..d9f9ebc327 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdatePersonOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdatePersonOperation : global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInUpdatePersonRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInRequest? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdatePersonOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdatePersonOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInUpdatePersonRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdatePersonOwnedTodoItemsRelationshipOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdatePersonOwnedTodoItemsRelationshipOperation.cs new file mode 100644 index 0000000000..d3897e3e91 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdatePersonOwnedTodoItemsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdatePersonOwnedTodoItemsRelationshipOperation : global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonOwnedTodoItemsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdatePersonOwnedTodoItemsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdatePersonOwnedTodoItemsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonOwnedTodoItemsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdatePersonRequestDocument.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdatePersonRequestDocument.cs new file mode 100644 index 0000000000..6a66c970c4 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdatePersonRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdatePersonRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInUpdatePersonRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdatePersonRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdatePersonRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdatePersonRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInUpdatePersonRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTagOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTagOperation.cs new file mode 100644 index 0000000000..a6f95262a7 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTagOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateTagOperation : global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInUpdateTagRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TagIdentifierInRequest? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTagOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTagOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInUpdateTagRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.TagIdentifierInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTagRequestDocument.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTagRequestDocument.cs new file mode 100644 index 0000000000..7bd46becea --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTagRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateTagRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInUpdateTagRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateTagRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTagRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTagRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInUpdateTagRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTagTodoItemsRelationshipOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTagTodoItemsRelationshipOperation.cs new file mode 100644 index 0000000000..d566ab853a --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTagTodoItemsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateTagTodoItemsRelationshipOperation : global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TagTodoItemsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTagTodoItemsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTagTodoItemsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.TagTodoItemsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTodoItemAssigneeRelationshipOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTodoItemAssigneeRelationshipOperation.cs new file mode 100644 index 0000000000..c97917c75b --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTodoItemAssigneeRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateTodoItemAssigneeRelationshipOperation : global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemAssigneeRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTodoItemAssigneeRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTodoItemAssigneeRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemAssigneeRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTodoItemOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTodoItemOperation.cs new file mode 100644 index 0000000000..6e98779249 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTodoItemOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateTodoItemOperation : global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInUpdateTodoItemRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierInRequest? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTodoItemOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTodoItemOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInUpdateTodoItemRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemIdentifierInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTodoItemOwnerRelationshipOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTodoItemOwnerRelationshipOperation.cs new file mode 100644 index 0000000000..15a12c97f3 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTodoItemOwnerRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateTodoItemOwnerRelationshipOperation : global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemOwnerRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTodoItemOwnerRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTodoItemOwnerRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.PersonIdentifierInRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemOwnerRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTodoItemRequestDocument.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTodoItemRequestDocument.cs new file mode 100644 index 0000000000..1d39ef6392 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTodoItemRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateTodoItemRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInUpdateTodoItemRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateTodoItemRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTodoItemRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTodoItemRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.DataInUpdateTodoItemRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTodoItemTagsRelationshipOperation.cs b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTodoItemTagsRelationshipOperation.cs new file mode 100644 index 0000000000..68b848e164 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/Models/UpdateTodoItemTagsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaClientExample.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateTodoItemTagsRelationshipOperation : global::OpenApiKiotaClientExample.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemTagsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTodoItemTagsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaClientExample.GeneratedCode.Models.UpdateTodoItemTagsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaClientExample.GeneratedCode.Models.TagIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaClientExample.GeneratedCode.Models.TodoItemTagsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/src/Examples/OpenApiKiotaClientExample/OpenApiKiotaClientExample.csproj b/src/Examples/OpenApiKiotaClientExample/OpenApiKiotaClientExample.csproj new file mode 100644 index 0000000000..8f65b2b688 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/OpenApiKiotaClientExample.csproj @@ -0,0 +1,28 @@ + + + net9.0 + + + + + + + + + + + + + + + + + + + $(MSBuildProjectName).GeneratedCode + ExampleApiClient + ./GeneratedCode + $(JsonApiExtraArguments) + + + diff --git a/src/Examples/OpenApiKiotaClientExample/PeopleMessageFormatter.cs b/src/Examples/OpenApiKiotaClientExample/PeopleMessageFormatter.cs new file mode 100644 index 0000000000..db22ae6231 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/PeopleMessageFormatter.cs @@ -0,0 +1,65 @@ +using System.Text; +using JetBrains.Annotations; +using OpenApiKiotaClientExample.GeneratedCode.Models; + +namespace OpenApiKiotaClientExample; + +/// +/// Prints the specified people, their assigned todo-items, and its tags. +/// +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +internal sealed class PeopleMessageFormatter +{ + public static void PrintPeople(PersonCollectionResponseDocument? peopleResponse) + { + string message = WritePeople(peopleResponse); + Console.WriteLine(message); + } + + private static string WritePeople(PersonCollectionResponseDocument? peopleResponse) + { + if (peopleResponse == null) + { + return "No response body was returned."; + } + + var builder = new StringBuilder(); + builder.AppendLine($"Found {peopleResponse.Data!.Count} people:"); + + foreach (DataInPersonResponse person in peopleResponse.Data) + { + WritePerson(person, peopleResponse.Included ?? [], builder); + } + + return builder.ToString(); + } + + private static void WritePerson(DataInPersonResponse person, List includes, StringBuilder builder) + { + List assignedTodoItems = person.Relationships?.AssignedTodoItems?.Data ?? []; + + builder.AppendLine($" Person {person.Id}: {person.Attributes?.DisplayName} with {assignedTodoItems.Count} assigned todo-items:"); + WriteRelatedTodoItems(assignedTodoItems, includes, builder); + } + + private static void WriteRelatedTodoItems(List todoItemIdentifiers, List includes, StringBuilder builder) + { + foreach (TodoItemIdentifierInResponse todoItemIdentifier in todoItemIdentifiers) + { + DataInTodoItemResponse includedTodoItem = includes.OfType().Single(include => include.Id == todoItemIdentifier.Id); + List tags = includedTodoItem.Relationships?.Tags?.Data ?? []; + + builder.AppendLine($" TodoItem {includedTodoItem.Id}: {includedTodoItem.Attributes?.Description} with {tags.Count} tags:"); + WriteRelatedTags(tags, includes, builder); + } + } + + private static void WriteRelatedTags(List tagIdentifiers, List includes, StringBuilder builder) + { + foreach (TagIdentifierInResponse tagIdentifier in tagIdentifiers) + { + DataInTagResponse includedTag = includes.OfType().Single(include => include.Id == tagIdentifier.Id); + builder.AppendLine($" Tag {includedTag.Id}: {includedTag.Attributes?.Name}"); + } + } +} diff --git a/src/Examples/OpenApiKiotaClientExample/Program.cs b/src/Examples/OpenApiKiotaClientExample/Program.cs new file mode 100644 index 0000000000..2716335282 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/Program.cs @@ -0,0 +1,37 @@ +using JsonApiDotNetCore.OpenApi.Client.Kiota; +using Microsoft.Kiota.Abstractions.Authentication; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaClientExample; +using OpenApiKiotaClientExample.GeneratedCode; + +HostApplicationBuilder builder = Host.CreateApplicationBuilder(args); +builder.Services.AddLogging(options => options.ClearProviders()); +builder.Services.AddHostedService(); +builder.Services.AddSingleton(); +builder.Services.AddSingleton(); +builder.Services.AddSingleton(); + +// @formatter:wrap_chained_method_calls chop_always +builder.Services.AddHttpClient() + .ConfigurePrimaryHttpMessageHandler(_ => + { + IList defaultHandlers = KiotaClientFactory.CreateDefaultHandlers(); + HttpMessageHandler defaultHttpMessageHandler = KiotaClientFactory.GetDefaultHttpMessageHandler(); + + // Or, if your generated client is long-lived, respond to DNS updates using: + // HttpMessageHandler defaultHttpMessageHandler = new SocketsHttpHandler(); + + return KiotaClientFactory.ChainHandlersCollectionAndGetFirstLink(defaultHttpMessageHandler, defaultHandlers.ToArray())!; + }) + .AddHttpMessageHandler() + .AddHttpMessageHandler() + .AddTypedClient((httpClient, serviceProvider) => + { + var authenticationProvider = serviceProvider.GetRequiredService(); + var requestAdapter = new HttpClientRequestAdapter(authenticationProvider, httpClient: httpClient); + return new ExampleApiClient(requestAdapter); + }); +// @formatter:wrap_chained_method_calls restore + +IHost host = builder.Build(); +await host.RunAsync(); diff --git a/src/Examples/OpenApiKiotaClientExample/Properties/launchSettings.json b/src/Examples/OpenApiKiotaClientExample/Properties/launchSettings.json new file mode 100644 index 0000000000..afb5e5dac4 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "profiles": { + "Kestrel": { + "commandName": "Project", + "dotnetRunMessages": true, + "environmentVariables": { + "DOTNET_ENVIRONMENT": "Development" + } + } + } +} diff --git a/src/Examples/OpenApiKiotaClientExample/Worker.cs b/src/Examples/OpenApiKiotaClientExample/Worker.cs new file mode 100644 index 0000000000..56c6cd6b0d --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/Worker.cs @@ -0,0 +1,212 @@ +using System.Net; +using JsonApiDotNetCore.OpenApi.Client.Kiota; +using Microsoft.Kiota.Abstractions; +using Microsoft.Kiota.Http.HttpClientLibrary.Middleware.Options; +using OpenApiKiotaClientExample.GeneratedCode; +using OpenApiKiotaClientExample.GeneratedCode.Models; + +namespace OpenApiKiotaClientExample; + +public sealed class Worker(ExampleApiClient apiClient, IHostApplicationLifetime hostApplicationLifetime, SetQueryStringHttpMessageHandler queryStringHandler) + : BackgroundService +{ + private readonly ExampleApiClient _apiClient = apiClient; + private readonly IHostApplicationLifetime _hostApplicationLifetime = hostApplicationLifetime; + private readonly SetQueryStringHttpMessageHandler _queryStringHandler = queryStringHandler; + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + try + { + using (_queryStringHandler.CreateScope(new Dictionary + { + // Workaround for https://github.com/microsoft/kiota/issues/3800. + ["filter"] = "has(assignedTodoItems)", + ["sort"] = "-lastName", + ["page[size]"] = "5", + ["include"] = "assignedTodoItems.tags" + })) + { + (PersonCollectionResponseDocument? getResponse, string? eTag) = await GetPeopleAsync(_apiClient, null, stoppingToken); + PeopleMessageFormatter.PrintPeople(getResponse); + + (PersonCollectionResponseDocument? getResponseAgain, _) = await GetPeopleAsync(_apiClient, eTag, stoppingToken); + PeopleMessageFormatter.PrintPeople(getResponseAgain); + } + + await UpdatePersonAsync(stoppingToken); + + await SendOperationsRequestAsync(stoppingToken); + + await _apiClient.Api.People["999999"].GetAsync(cancellationToken: stoppingToken); + } + catch (ErrorResponseDocument exception) + { + Console.WriteLine($"JSON:API ERROR: {exception.Errors!.First().Detail}"); + } + catch (HttpRequestException exception) + { + Console.WriteLine($"ERROR: {exception.Message}"); + } + + _hostApplicationLifetime.StopApplication(); + } + + private static async Task<(PersonCollectionResponseDocument? response, string? eTag)> GetPeopleAsync(ExampleApiClient apiClient, string? ifNoneMatch, + CancellationToken cancellationToken) + { + try + { + var headerInspector = new HeadersInspectionHandlerOption + { + InspectResponseHeaders = true + }; + + PersonCollectionResponseDocument? response = await apiClient.Api.People.GetAsync(configuration => + { + if (!string.IsNullOrEmpty(ifNoneMatch)) + { + configuration.Headers.Add("If-None-Match", ifNoneMatch); + } + + configuration.Options.Add(headerInspector); + }, cancellationToken); + + string eTag = headerInspector.ResponseHeaders["ETag"].Single(); + + return (response, eTag); + } + // Workaround for https://github.com/microsoft/kiota/issues/4190. + catch (ApiException exception) when (exception.ResponseStatusCode == (int)HttpStatusCode.NotModified) + { + return (null, null); + } + } + + private async Task UpdatePersonAsync(CancellationToken cancellationToken) + { + var updatePersonRequest = new UpdatePersonRequestDocument + { + Data = new DataInUpdatePersonRequest + { + Type = ResourceType.People, + Id = "1", + Attributes = new AttributesInUpdatePersonRequest + { + // The --backing-store switch enables to send null and default values. + FirstName = null, + LastName = "Doe" + } + } + }; + + await _apiClient.Api.People[updatePersonRequest.Data.Id].PatchAsync(updatePersonRequest, cancellationToken: cancellationToken); + } + + private async Task SendOperationsRequestAsync(CancellationToken cancellationToken) + { + var operationsRequest = new OperationsRequestDocument + { + AtomicOperations = + [ + new CreateTagOperation + { + Op = AddOperationCode.Add, + Data = new DataInCreateTagRequest + { + Type = ResourceType.Tags, + Lid = "new-tag", + Attributes = new AttributesInCreateTagRequest + { + Name = "Housekeeping" + } + } + }, + new CreatePersonOperation + { + Op = AddOperationCode.Add, + Data = new DataInCreatePersonRequest + { + Type = ResourceType.People, + Lid = "new-person", + Attributes = new AttributesInCreatePersonRequest + { + FirstName = "Cinderella", + LastName = "Tremaine" + } + } + }, + new UpdatePersonOperation + { + Op = UpdateOperationCode.Update, + Data = new DataInUpdatePersonRequest + { + Type = ResourceType.People, + Lid = "new-person", + Attributes = new AttributesInUpdatePersonRequest + { + // The --backing-store switch enables to send null and default values. + FirstName = null + } + } + }, + new CreateTodoItemOperation + { + Op = AddOperationCode.Add, + Data = new DataInCreateTodoItemRequest + { + Type = ResourceType.TodoItems, + Lid = "new-todo-item", + Attributes = new AttributesInCreateTodoItemRequest + { + Description = "Put out the garbage", + Priority = TodoItemPriority.Medium + }, + Relationships = new RelationshipsInCreateTodoItemRequest + { + Owner = new ToOnePersonInRequest + { + Data = new PersonIdentifierInRequest + { + Type = ResourceType.People, + Lid = "new-person" + } + }, + Tags = new ToManyTagInRequest + { + Data = + [ + new TagIdentifierInRequest + { + Type = ResourceType.Tags, + Lid = "new-tag" + } + ] + } + } + } + }, + new UpdateTodoItemAssigneeRelationshipOperation + { + Op = UpdateOperationCode.Update, + Ref = new TodoItemAssigneeRelationshipIdentifier + { + Type = TodoItemResourceType.TodoItems, + Lid = "new-todo-item", + Relationship = TodoItemAssigneeRelationshipName.Assignee + }, + Data = new PersonIdentifierInRequest + { + Type = ResourceType.People, + Lid = "new-person" + } + } + ] + }; + + OperationsResponseDocument? operationsResponse = await _apiClient.Api.Operations.PostAsync(operationsRequest, cancellationToken: cancellationToken); + + var newTodoItem = (DataInTodoItemResponse)operationsResponse!.AtomicResults!.ElementAt(3).Data!; + Console.WriteLine($"Created todo-item with ID {newTodoItem.Id}: {newTodoItem.Attributes!.Description}."); + } +} diff --git a/src/Examples/OpenApiKiotaClientExample/appsettings.json b/src/Examples/OpenApiKiotaClientExample/appsettings.json new file mode 100644 index 0000000000..2b94cdb46d --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Warning", + "Microsoft.Hosting.Lifetime": "Information", + "System.Net.Http.HttpClient": "Information" + } + } +} diff --git a/src/Examples/OpenApiNSwagClientExample/.editorconfig b/src/Examples/OpenApiNSwagClientExample/.editorconfig new file mode 100644 index 0000000000..e2ec1cac44 --- /dev/null +++ b/src/Examples/OpenApiNSwagClientExample/.editorconfig @@ -0,0 +1,3 @@ +# Workaround for incorrect nullability in NSwag generated clients. +[*Client.cs] +dotnet_diagnostic.CS8765.severity = none diff --git a/src/Examples/OpenApiNSwagClientExample/ColoredConsoleLogHttpMessageHandler.cs b/src/Examples/OpenApiNSwagClientExample/ColoredConsoleLogHttpMessageHandler.cs new file mode 100644 index 0000000000..d999a7d9bf --- /dev/null +++ b/src/Examples/OpenApiNSwagClientExample/ColoredConsoleLogHttpMessageHandler.cs @@ -0,0 +1,67 @@ +using JetBrains.Annotations; + +namespace OpenApiNSwagClientExample; + +/// +/// Writes incoming and outgoing HTTP messages to the console. +/// +internal sealed class ColoredConsoleLogHttpMessageHandler : DelegatingHandler +{ + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { +#if DEBUG + await LogRequestAsync(request, cancellationToken); +#endif + + HttpResponseMessage response = await base.SendAsync(request, cancellationToken); + +#if DEBUG + await LogResponseAsync(response, cancellationToken); +#endif + + return response; + } + + [UsedImplicitly] + private static async Task LogRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + using var _ = new ConsoleColorScope(ConsoleColor.Green); + + Console.WriteLine($"--> {request}"); + string? requestBody = request.Content != null ? await request.Content.ReadAsStringAsync(cancellationToken) : null; + + if (!string.IsNullOrEmpty(requestBody)) + { + Console.WriteLine(); + Console.WriteLine(requestBody); + } + } + + [UsedImplicitly] + private static async Task LogResponseAsync(HttpResponseMessage response, CancellationToken cancellationToken) + { + using var _ = new ConsoleColorScope(ConsoleColor.Cyan); + + Console.WriteLine($"<-- {response}"); + string responseBody = await response.Content.ReadAsStringAsync(cancellationToken); + + if (!string.IsNullOrEmpty(responseBody)) + { + Console.WriteLine(); + Console.WriteLine(responseBody); + } + } + + private sealed class ConsoleColorScope : IDisposable + { + public ConsoleColorScope(ConsoleColor foregroundColor) + { + Console.ForegroundColor = foregroundColor; + } + + public void Dispose() + { + Console.ResetColor(); + } + } +} diff --git a/src/Examples/OpenApiNSwagClientExample/OpenApiNSwagClientExample.csproj b/src/Examples/OpenApiNSwagClientExample/OpenApiNSwagClientExample.csproj new file mode 100644 index 0000000000..c30833a39a --- /dev/null +++ b/src/Examples/OpenApiNSwagClientExample/OpenApiNSwagClientExample.csproj @@ -0,0 +1,31 @@ + + + + net9.0 + + + + + + + + + + + + + + + + + + + + ExampleApi + $(MSBuildProjectName) + %(Name)Client + %(ClassName).cs + true + + + diff --git a/src/Examples/OpenApiNSwagClientExample/PeopleMessageFormatter.cs b/src/Examples/OpenApiNSwagClientExample/PeopleMessageFormatter.cs new file mode 100644 index 0000000000..0a870d7682 --- /dev/null +++ b/src/Examples/OpenApiNSwagClientExample/PeopleMessageFormatter.cs @@ -0,0 +1,66 @@ +using System.Text; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Client.NSwag; + +namespace OpenApiNSwagClientExample; + +/// +/// Prints the specified people, their assigned todo-items, and its tags. +/// +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +internal sealed class PeopleMessageFormatter +{ + public static void PrintPeople(ApiResponse peopleResponse) + { + string message = WritePeople(peopleResponse); + Console.WriteLine(message); + } + + private static string WritePeople(ApiResponse peopleResponse) + { + if (peopleResponse.Result == null) + { + return $"Status code {peopleResponse.StatusCode} was returned without a response body."; + } + + var builder = new StringBuilder(); + builder.AppendLine($"Found {peopleResponse.Result.Data.Count} people:"); + + foreach (DataInPersonResponse person in peopleResponse.Result.Data) + { + WritePerson(person, peopleResponse.Result.Included ?? [], builder); + } + + return builder.ToString(); + } + + private static void WritePerson(DataInPersonResponse person, ICollection includes, StringBuilder builder) + { + ICollection assignedTodoItems = person.Relationships?.AssignedTodoItems?.Data ?? []; + + builder.AppendLine($" Person {person.Id}: {person.Attributes?.DisplayName} with {assignedTodoItems.Count} assigned todo-items:"); + WriteRelatedTodoItems(assignedTodoItems, includes, builder); + } + + private static void WriteRelatedTodoItems(IEnumerable todoItemIdentifiers, ICollection includes, + StringBuilder builder) + { + foreach (TodoItemIdentifierInResponse todoItemIdentifier in todoItemIdentifiers) + { + DataInTodoItemResponse includedTodoItem = includes.OfType().Single(include => include.Id == todoItemIdentifier.Id); + ICollection tags = includedTodoItem.Relationships?.Tags?.Data ?? []; + + builder.AppendLine($" TodoItem {includedTodoItem.Id}: {includedTodoItem.Attributes?.Description} with {tags.Count} tags:"); + WriteRelatedTags(tags, includes, builder); + } + } + + private static void WriteRelatedTags(IEnumerable tagIdentifiers, ICollection includes, StringBuilder builder) + { + foreach (TagIdentifierInResponse tagIdentifier in tagIdentifiers) + { + DataInTagResponse includedTag = includes.OfType().Single(include => include.Id == tagIdentifier.Id); + builder.AppendLine($" Tag {includedTag.Id}: {includedTag.Attributes?.Name}"); + } + } +} diff --git a/src/Examples/OpenApiNSwagClientExample/Program.cs b/src/Examples/OpenApiNSwagClientExample/Program.cs new file mode 100644 index 0000000000..67d81a7ad1 --- /dev/null +++ b/src/Examples/OpenApiNSwagClientExample/Program.cs @@ -0,0 +1,10 @@ +using OpenApiNSwagClientExample; + +HostApplicationBuilder builder = Host.CreateApplicationBuilder(args); +builder.Services.AddLogging(options => options.ClearProviders()); +builder.Services.AddHostedService(); +builder.Services.AddSingleton(); +builder.Services.AddHttpClient().AddHttpMessageHandler(); + +IHost host = builder.Build(); +await host.RunAsync(); diff --git a/src/Examples/OpenApiNSwagClientExample/Properties/launchSettings.json b/src/Examples/OpenApiNSwagClientExample/Properties/launchSettings.json new file mode 100644 index 0000000000..afb5e5dac4 --- /dev/null +++ b/src/Examples/OpenApiNSwagClientExample/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "profiles": { + "Kestrel": { + "commandName": "Project", + "dotnetRunMessages": true, + "environmentVariables": { + "DOTNET_ENVIRONMENT": "Development" + } + } + } +} diff --git a/src/Examples/OpenApiNSwagClientExample/Worker.cs b/src/Examples/OpenApiNSwagClientExample/Worker.cs new file mode 100644 index 0000000000..7727c88a15 --- /dev/null +++ b/src/Examples/OpenApiNSwagClientExample/Worker.cs @@ -0,0 +1,171 @@ +using JsonApiDotNetCore.OpenApi.Client.NSwag; + +namespace OpenApiNSwagClientExample; + +public sealed class Worker(ExampleApiClient apiClient, IHostApplicationLifetime hostApplicationLifetime) : BackgroundService +{ + private readonly ExampleApiClient _apiClient = apiClient; + private readonly IHostApplicationLifetime _hostApplicationLifetime = hostApplicationLifetime; + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + try + { + var queryString = new Dictionary + { + ["filter"] = "has(assignedTodoItems)", + ["sort"] = "-lastName", + ["page[size]"] = "5", + ["include"] = "assignedTodoItems.tags" + }; + + ApiResponse getResponse = await GetPeopleAsync(_apiClient, queryString, null, stoppingToken); + PeopleMessageFormatter.PrintPeople(getResponse); + + string eTag = getResponse.Headers["ETag"].Single(); + ApiResponse getResponseAgain = await GetPeopleAsync(_apiClient, queryString, eTag, stoppingToken); + PeopleMessageFormatter.PrintPeople(getResponseAgain); + + await UpdatePersonAsync(stoppingToken); + + await SendOperationsRequestAsync(stoppingToken); + + await _apiClient.GetPersonAsync("999999", null, null, stoppingToken); + } + catch (ApiException exception) + { + Console.WriteLine($"JSON:API ERROR: {exception.Result.Errors.First().Detail}"); + } + catch (HttpRequestException exception) + { + Console.WriteLine($"ERROR: {exception.Message}"); + } + + _hostApplicationLifetime.StopApplication(); + } + + private static Task> GetPeopleAsync(ExampleApiClient apiClient, IDictionary queryString, + string? ifNoneMatch, CancellationToken cancellationToken) + { + return ApiResponse.TranslateAsync(async () => await apiClient.GetPersonCollectionAsync(queryString, ifNoneMatch, cancellationToken)); + } + + private async Task UpdatePersonAsync(CancellationToken cancellationToken) + { + var updatePersonRequest = new UpdatePersonRequestDocument + { + Data = new DataInUpdatePersonRequest + { + Id = "1", + // Using TrackChangesFor to send "firstName: null" instead of omitting it. + Attributes = new TrackChangesFor(_apiClient) + { + Initializer = + { + FirstName = null, + LastName = "Doe" + } + }.Initializer + } + }; + + await ApiResponse.TranslateAsync(async () => + await _apiClient.PatchPersonAsync(updatePersonRequest.Data.Id, updatePersonRequest, cancellationToken: cancellationToken)); + } + + private async Task SendOperationsRequestAsync(CancellationToken cancellationToken) + { + var operationsRequest = new OperationsRequestDocument + { + Atomic_operations = + [ + new CreateTagOperation + { + Data = new DataInCreateTagRequest + { + Lid = "new-tag", + Attributes = new AttributesInCreateTagRequest + { + Name = "Housekeeping" + } + } + }, + new CreatePersonOperation + { + Data = new DataInCreatePersonRequest + { + Lid = "new-person", + Attributes = new AttributesInCreatePersonRequest + { + FirstName = "Cinderella", + LastName = "Tremaine" + } + } + }, + new UpdatePersonOperation + { + Data = new DataInUpdatePersonRequest + { + Lid = "new-person", + // Using TrackChangesFor to send "firstName: null" instead of omitting it. + Attributes = new TrackChangesFor(_apiClient) + { + Initializer = + { + FirstName = null + } + }.Initializer + } + }, + new CreateTodoItemOperation + { + Data = new DataInCreateTodoItemRequest + { + Lid = "new-todo-item", + Attributes = new AttributesInCreateTodoItemRequest + { + Description = "Put out the garbage", + Priority = TodoItemPriority.Medium + }, + Relationships = new RelationshipsInCreateTodoItemRequest + { + Owner = new ToOnePersonInRequest + { + Data = new PersonIdentifierInRequest + { + Lid = "new-person" + } + }, + Tags = new ToManyTagInRequest + { + Data = + [ + new TagIdentifierInRequest + { + Lid = "new-tag" + } + ] + } + } + } + }, + new UpdateTodoItemAssigneeRelationshipOperation + { + Ref = new TodoItemAssigneeRelationshipIdentifier + { + Lid = "new-todo-item" + }, + Data = new PersonIdentifierInRequest + { + Lid = "new-person" + } + } + ] + }; + + ApiResponse operationsResponse = await _apiClient.PostOperationsAsync(operationsRequest, cancellationToken); + + var newTodoItem = (DataInTodoItemResponse)operationsResponse.Result.Atomic_results.ElementAt(3).Data!; + Console.WriteLine($"Created todo-item with ID {newTodoItem.Id}: {newTodoItem.Attributes!.Description}."); + } +} diff --git a/src/Examples/OpenApiNSwagClientExample/appsettings.json b/src/Examples/OpenApiNSwagClientExample/appsettings.json new file mode 100644 index 0000000000..2b94cdb46d --- /dev/null +++ b/src/Examples/OpenApiNSwagClientExample/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Warning", + "Microsoft.Hosting.Lifetime": "Information", + "System.Net.Http.HttpClient": "Information" + } + } +} diff --git a/src/Examples/ReportsExample/Program.cs b/src/Examples/ReportsExample/Program.cs index 04920d0068..7f89ad9301 100644 --- a/src/Examples/ReportsExample/Program.cs +++ b/src/Examples/ReportsExample/Program.cs @@ -24,4 +24,4 @@ app.UseJsonApi(); app.MapControllers(); -app.Run(); +await app.RunAsync(); diff --git a/src/Examples/ReportsExample/ReportsExample.csproj b/src/Examples/ReportsExample/ReportsExample.csproj index bff4909317..6ade1386be 100644 --- a/src/Examples/ReportsExample/ReportsExample.csproj +++ b/src/Examples/ReportsExample/ReportsExample.csproj @@ -1,6 +1,6 @@ - net8.0;net6.0 + net9.0;net8.0 diff --git a/src/Examples/ReportsExample/Services/ReportService.cs b/src/Examples/ReportsExample/Services/ReportService.cs index c04e821347..62bb7c9554 100644 --- a/src/Examples/ReportsExample/Services/ReportService.cs +++ b/src/Examples/ReportsExample/Services/ReportService.cs @@ -5,24 +5,19 @@ namespace ReportsExample.Services; [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] -public class ReportService(ILoggerFactory loggerFactory) : IGetAllService +public class ReportService : IGetAllService { - private readonly ILogger _logger = loggerFactory.CreateLogger(); - public Task> GetAsync(CancellationToken cancellationToken) { - _logger.LogInformation("GetAsync"); - - IReadOnlyCollection reports = GetReports(); - + IReadOnlyCollection reports = GetReports().AsReadOnly(); return Task.FromResult(reports); } - private IReadOnlyCollection GetReports() + private List GetReports() { - return new List - { - new() + return + [ + new Report { Id = 1, Title = "Status Report", @@ -32,6 +27,6 @@ private IReadOnlyCollection GetReports() HoursSpent = 24 } } - }; + ]; } } diff --git a/src/JsonApiDotNetCore.Annotations/ArgumentGuard.cs b/src/JsonApiDotNetCore.Annotations/ArgumentGuard.cs index 4264c5db8b..1eea1c3841 100644 --- a/src/JsonApiDotNetCore.Annotations/ArgumentGuard.cs +++ b/src/JsonApiDotNetCore.Annotations/ArgumentGuard.cs @@ -3,20 +3,14 @@ using SysNotNull = System.Diagnostics.CodeAnalysis.NotNullAttribute; #pragma warning disable AV1008 // Class should not be static +#pragma warning disable format namespace JsonApiDotNetCore; internal static class ArgumentGuard { [AssertionMethod] - public static void NotNull([NoEnumeration] [SysNotNull] T? value, [CallerArgumentExpression("value")] string? parameterName = null) - where T : class - { - ArgumentNullException.ThrowIfNull(value, parameterName); - } - - [AssertionMethod] - public static void NotNullNorEmpty([SysNotNull] IEnumerable? value, [CallerArgumentExpression("value")] string? parameterName = null) + public static void NotNullNorEmpty([SysNotNull] IEnumerable? value, [CallerArgumentExpression(nameof(value))] string? parameterName = null) { ArgumentNullException.ThrowIfNull(value, parameterName); @@ -25,15 +19,4 @@ public static void NotNullNorEmpty([SysNotNull] IEnumerable? value, [Calle throw new ArgumentException("Collection cannot be null or empty.", parameterName); } } - - [AssertionMethod] - public static void NotNullNorEmpty([SysNotNull] string? value, [CallerArgumentExpression("value")] string? parameterName = null) - { - ArgumentNullException.ThrowIfNull(value, parameterName); - - if (value == string.Empty) - { - throw new ArgumentException("String cannot be null or empty.", parameterName); - } - } } diff --git a/src/JsonApiDotNetCore.Annotations/CollectionConverter.cs b/src/JsonApiDotNetCore.Annotations/CollectionConverter.cs index e95d306329..cbf834b630 100644 --- a/src/JsonApiDotNetCore.Annotations/CollectionConverter.cs +++ b/src/JsonApiDotNetCore.Annotations/CollectionConverter.cs @@ -5,15 +5,21 @@ namespace JsonApiDotNetCore; internal sealed class CollectionConverter { - private static readonly ISet HashSetCompatibleCollectionTypes = new HashSet - { + private static readonly HashSet HashSetCompatibleCollectionTypes = + [ typeof(HashSet<>), typeof(ISet<>), typeof(IReadOnlySet<>), typeof(ICollection<>), typeof(IReadOnlyCollection<>), typeof(IEnumerable<>) - }; + ]; + + public static CollectionConverter Instance { get; } = new(); + + private CollectionConverter() + { + } /// /// Creates a collection instance based on the specified collection type and copies the specified elements into it. @@ -22,12 +28,16 @@ internal sealed class CollectionConverter /// Source to copy from. /// /// - /// Target collection type, for example: typeof(List{Article}) or typeof(ISet{Person}). + /// Target collection type, for example: ) + /// ]]> or ) + /// ]]>. /// public IEnumerable CopyToTypedCollection(IEnumerable source, Type collectionType) { - ArgumentGuard.NotNull(source); - ArgumentGuard.NotNull(collectionType); + ArgumentNullException.ThrowIfNull(source); + ArgumentNullException.ThrowIfNull(collectionType); Type concreteCollectionType = ToConcreteCollectionType(collectionType); dynamic concreteCollectionInstance = Activator.CreateInstance(concreteCollectionType)!; @@ -41,7 +51,12 @@ public IEnumerable CopyToTypedCollection(IEnumerable source, Type collectionType } /// - /// Returns a compatible collection type that can be instantiated, for example IList{Article} -> List{Article} or ISet{Article} -> HashSet{Article} + /// Returns a compatible collection type that can be instantiated, for example: -> List
+ /// ]]> or + /// -> HashSet
+ /// ]]>. ///
private Type ToConcreteCollectionType(Type collectionType) { @@ -70,17 +85,22 @@ public IReadOnlyCollection ExtractResources(object? value) { return value switch { - List resourceList => resourceList, - HashSet resourceSet => resourceSet, + List resourceList => resourceList.AsReadOnly(), + HashSet resourceSet => resourceSet.AsReadOnly(), IReadOnlyCollection resourceCollection => resourceCollection, - IEnumerable resources => resources.ToList(), + IEnumerable resources => resources.ToArray().AsReadOnly(), IIdentifiable resource => [resource], _ => Array.Empty() }; } /// - /// Returns the element type if the specified type is a generic collection, for example: IList{string} -> string or IList -> null. + /// Returns the element type if the specified type is a generic collection, for example: -> string + /// ]]> or + /// null + /// ]]>. /// public Type? FindCollectionElementType(Type? type) { @@ -96,12 +116,16 @@ public IReadOnlyCollection ExtractResources(object? value) } /// - /// Indicates whether a instance can be assigned to the specified type, for example IList{Article} -> false or ISet{Article} -> - /// true. + /// Indicates whether a instance can be assigned to the specified type, for example: + /// -> false + /// ]]> or -> true + /// ]]>. /// public bool TypeCanContainHashSet(Type collectionType) { - ArgumentGuard.NotNull(collectionType); + ArgumentNullException.ThrowIfNull(collectionType); if (collectionType.IsGenericType) { diff --git a/src/JsonApiDotNetCore.Annotations/Configuration/ResourceType.cs b/src/JsonApiDotNetCore.Annotations/Configuration/ResourceType.cs index 47542def56..3cda945d74 100644 --- a/src/JsonApiDotNetCore.Annotations/Configuration/ResourceType.cs +++ b/src/JsonApiDotNetCore.Annotations/Configuration/ResourceType.cs @@ -9,6 +9,10 @@ namespace JsonApiDotNetCore.Configuration; [PublicAPI] public sealed class ResourceType { + private static readonly IReadOnlySet EmptyResourceTypeSet = new HashSet().AsReadOnly(); + private static readonly IReadOnlySet EmptyAttributeSet = new HashSet().AsReadOnly(); + private static readonly IReadOnlySet EmptyRelationshipSet = new HashSet().AsReadOnly(); + private readonly Dictionary _fieldsByPublicName = []; private readonly Dictionary _fieldsByPropertyName = []; private readonly Lazy> _lazyAllConcreteDerivedTypes; @@ -42,7 +46,7 @@ public sealed class ResourceType /// /// The resource types that directly derive from this one. /// - public IReadOnlySet DirectlyDerivedTypes { get; internal set; } = new HashSet(); + public IReadOnlySet DirectlyDerivedTypes { get; internal set; } = EmptyResourceTypeSet; /// /// Exposed resource attributes and relationships. See https://jsonapi.org/format/#document-resource-object-fields. When using resource inheritance, this @@ -107,9 +111,9 @@ public ResourceType(string publicName, ClientIdGenerationMode? clientIdGeneratio IReadOnlyCollection? eagerLoads, LinkTypes topLevelLinks = LinkTypes.NotConfigured, LinkTypes resourceLinks = LinkTypes.NotConfigured, LinkTypes relationshipLinks = LinkTypes.NotConfigured) { - ArgumentGuard.NotNullNorEmpty(publicName); - ArgumentGuard.NotNull(clrType); - ArgumentGuard.NotNull(identityClrType); + ArgumentException.ThrowIfNullOrWhiteSpace(publicName); + ArgumentNullException.ThrowIfNull(clrType); + ArgumentNullException.ThrowIfNull(identityClrType); PublicName = publicName; ClientIdGeneration = clientIdGeneration; @@ -121,7 +125,7 @@ public ResourceType(string publicName, ClientIdGenerationMode? clientIdGeneratio TopLevelLinks = topLevelLinks; ResourceLinks = resourceLinks; RelationshipLinks = relationshipLinks; - Fields = Attributes.Cast().Concat(Relationships).ToArray(); + Fields = Attributes.Cast().Concat(Relationships).ToArray().AsReadOnly(); foreach (ResourceFieldAttribute field in Fields) { @@ -134,10 +138,10 @@ public ResourceType(string publicName, ClientIdGenerationMode? clientIdGeneratio private IReadOnlySet ResolveAllConcreteDerivedTypes() { - var allConcreteDerivedTypes = new HashSet(); + HashSet allConcreteDerivedTypes = []; AddConcreteDerivedTypes(this, allConcreteDerivedTypes); - return allConcreteDerivedTypes; + return allConcreteDerivedTypes.AsReadOnly(); } private static void AddConcreteDerivedTypes(ResourceType resourceType, ISet allConcreteDerivedTypes) @@ -161,7 +165,7 @@ public AttrAttribute GetAttributeByPublicName(string publicName) public AttrAttribute? FindAttributeByPublicName(string publicName) { - ArgumentGuard.NotNull(publicName); + ArgumentNullException.ThrowIfNull(publicName); return _fieldsByPublicName.TryGetValue(publicName, out ResourceFieldAttribute? field) && field is AttrAttribute attribute ? attribute : null; } @@ -175,7 +179,7 @@ public AttrAttribute GetAttributeByPropertyName(string propertyName) public AttrAttribute? FindAttributeByPropertyName(string propertyName) { - ArgumentGuard.NotNull(propertyName); + ArgumentNullException.ThrowIfNull(propertyName); return _fieldsByPropertyName.TryGetValue(propertyName, out ResourceFieldAttribute? field) && field is AttrAttribute attribute ? attribute : null; } @@ -188,7 +192,7 @@ public RelationshipAttribute GetRelationshipByPublicName(string publicName) public RelationshipAttribute? FindRelationshipByPublicName(string publicName) { - ArgumentGuard.NotNull(publicName); + ArgumentNullException.ThrowIfNull(publicName); return _fieldsByPublicName.TryGetValue(publicName, out ResourceFieldAttribute? field) && field is RelationshipAttribute relationship ? relationship @@ -205,7 +209,7 @@ public RelationshipAttribute GetRelationshipByPropertyName(string propertyName) public RelationshipAttribute? FindRelationshipByPropertyName(string propertyName) { - ArgumentGuard.NotNull(propertyName); + ArgumentNullException.ThrowIfNull(propertyName); return _fieldsByPropertyName.TryGetValue(propertyName, out ResourceFieldAttribute? field) && field is RelationshipAttribute relationship ? relationship @@ -213,7 +217,7 @@ public RelationshipAttribute GetRelationshipByPropertyName(string propertyName) } /// - /// Returns all directly and indirectly non-abstract resource types that derive from this resource type. + /// Returns all non-abstract resource types that directly or indirectly derive from this resource type. /// public IReadOnlySet GetAllConcreteDerivedTypes() { @@ -225,7 +229,7 @@ public IReadOnlySet GetAllConcreteDerivedTypes() /// public ResourceType GetTypeOrDerived(Type clrType) { - ArgumentGuard.NotNull(clrType); + ArgumentNullException.ThrowIfNull(clrType); ResourceType? derivedType = FindTypeOrDerived(this, clrType); @@ -259,7 +263,20 @@ public ResourceType GetTypeOrDerived(Type clrType) internal IReadOnlySet GetAttributesInTypeOrDerived(string publicName) { - return GetAttributesInTypeOrDerived(this, publicName); + if (IsPartOfTypeHierarchy()) + { + return GetAttributesInTypeOrDerived(this, publicName); + } + + AttrAttribute? attribute = FindAttributeByPublicName(publicName); + + if (attribute == null) + { + return EmptyAttributeSet; + } + + HashSet attributes = [attribute]; + return attributes.AsReadOnly(); } private static IReadOnlySet GetAttributesInTypeOrDerived(ResourceType resourceType, string publicName) @@ -268,7 +285,8 @@ private static IReadOnlySet GetAttributesInTypeOrDerived(Resource if (attribute != null) { - return attribute.AsHashSet(); + HashSet attributes = [attribute]; + return attributes.AsReadOnly(); } // Hiding base members using the 'new' keyword instead of 'override' (effectively breaking inheritance) is currently not supported. @@ -281,12 +299,25 @@ private static IReadOnlySet GetAttributesInTypeOrDerived(Resource attributesInDerivedTypes.Add(attributeInDerivedType); } - return attributesInDerivedTypes; + return attributesInDerivedTypes.AsReadOnly(); } internal IReadOnlySet GetRelationshipsInTypeOrDerived(string publicName) { - return GetRelationshipsInTypeOrDerived(this, publicName); + if (IsPartOfTypeHierarchy()) + { + return GetRelationshipsInTypeOrDerived(this, publicName); + } + + RelationshipAttribute? relationship = FindRelationshipByPublicName(publicName); + + if (relationship == null) + { + return EmptyRelationshipSet; + } + + HashSet relationships = [relationship]; + return relationships.AsReadOnly(); } private static IReadOnlySet GetRelationshipsInTypeOrDerived(ResourceType resourceType, string publicName) @@ -295,7 +326,8 @@ private static IReadOnlySet GetRelationshipsInTypeOrDeriv if (relationship != null) { - return relationship.AsHashSet(); + HashSet relationships = [relationship]; + return relationships.AsReadOnly(); } // Hiding base members using the 'new' keyword instead of 'override' (effectively breaking inheritance) is currently not supported. @@ -309,12 +341,12 @@ private static IReadOnlySet GetRelationshipsInTypeOrDeriv relationshipsInDerivedTypes.Add(relationshipInDerivedType); } - return relationshipsInDerivedTypes; + return relationshipsInDerivedTypes.AsReadOnly(); } internal bool IsPartOfTypeHierarchy() { - return BaseType != null || DirectlyDerivedTypes.Any(); + return BaseType != null || DirectlyDerivedTypes.Count > 0; } public override string ToString() diff --git a/src/JsonApiDotNetCore.Annotations/JsonApiDotNetCore.Annotations.csproj b/src/JsonApiDotNetCore.Annotations/JsonApiDotNetCore.Annotations.csproj index 04238621da..765c4231d7 100644 --- a/src/JsonApiDotNetCore.Annotations/JsonApiDotNetCore.Annotations.csproj +++ b/src/JsonApiDotNetCore.Annotations/JsonApiDotNetCore.Annotations.csproj @@ -1,6 +1,6 @@ - net8.0;net6.0;netstandard1.0 + net8.0;netstandard1.0 true true JsonApiDotNetCore @@ -9,7 +9,6 @@ - $(JsonApiDotNetCoreVersionPrefix) jsonapidotnetcore;jsonapi;json:api;dotnet;asp.net;rest;web-api Annotations for JsonApiDotNetCore, a framework for building JSON:API compliant REST APIs using ASP.NET and Entity Framework Core. json-api-dotnet @@ -20,7 +19,6 @@ package-icon.png PackageReadme.md true - true embedded @@ -47,7 +45,6 @@ - diff --git a/src/JsonApiDotNetCore.Annotations/ObjectExtensions.cs b/src/JsonApiDotNetCore.Annotations/ObjectExtensions.cs deleted file mode 100644 index 8aa1e6c165..0000000000 --- a/src/JsonApiDotNetCore.Annotations/ObjectExtensions.cs +++ /dev/null @@ -1,11 +0,0 @@ -#pragma warning disable AV1130 // Return type in method signature should be an interface to an unchangeable collection - -namespace JsonApiDotNetCore; - -internal static class ObjectExtensions -{ - public static HashSet AsHashSet(this T element) - { - return [element]; - } -} diff --git a/src/JsonApiDotNetCore.Annotations/PolyfillCollectionExtensions.cs b/src/JsonApiDotNetCore.Annotations/PolyfillCollectionExtensions.cs new file mode 100644 index 0000000000..efc51f4f17 --- /dev/null +++ b/src/JsonApiDotNetCore.Annotations/PolyfillCollectionExtensions.cs @@ -0,0 +1,12 @@ +using System.Collections.ObjectModel; + +namespace JsonApiDotNetCore; + +// These methods provide polyfills for lower .NET versions. +internal static class PolyfillCollectionExtensions +{ + public static IReadOnlySet AsReadOnly(this HashSet source) + { + return new ReadOnlySet(source); + } +} diff --git a/src/JsonApiDotNetCore.Annotations/Properties/AssemblyInfo.cs b/src/JsonApiDotNetCore.Annotations/Properties/AssemblyInfo.cs index a715457d54..b4ac4b1e8d 100644 --- a/src/JsonApiDotNetCore.Annotations/Properties/AssemblyInfo.cs +++ b/src/JsonApiDotNetCore.Annotations/Properties/AssemblyInfo.cs @@ -3,6 +3,7 @@ [assembly: InternalsVisibleTo("DapperExample")] [assembly: InternalsVisibleTo("Benchmarks")] [assembly: InternalsVisibleTo("JsonApiDotNetCore")] +[assembly: InternalsVisibleTo("JsonApiDotNetCore.OpenApi.Swashbuckle")] [assembly: InternalsVisibleTo("JsonApiDotNetCoreTests")] [assembly: InternalsVisibleTo("UnitTests")] [assembly: InternalsVisibleTo("TestBuildingBlocks")] diff --git a/src/JsonApiDotNetCore.Annotations/ReadOnlySet.cs b/src/JsonApiDotNetCore.Annotations/ReadOnlySet.cs new file mode 100644 index 0000000000..9917af9ec7 --- /dev/null +++ b/src/JsonApiDotNetCore.Annotations/ReadOnlySet.cs @@ -0,0 +1,171 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#if NET8_0 +#pragma warning disable + +// ReadOnlySet was introduced in .NET 9. +// This file was copied from https://github.com/dotnet/runtime/blob/release/9.0/src/libraries/System.Collections/src/System/Collections/Generic/ReadOnlySet.cs +// and made internal to enable usage on lower .NET versions. + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; + +namespace System.Collections.ObjectModel; + +/// Represents a read-only, generic set of values. +/// The type of values in the set. +[DebuggerDisplay("Count = {Count}")] +[ExcludeFromCodeCoverage] +internal class ReadOnlySet : IReadOnlySet, ISet, ICollection +{ + /// The wrapped set. + private readonly ISet _set; + + /// Initializes a new instance of the class that is a wrapper around the specified set. + /// The set to wrap. + public ReadOnlySet(ISet set) + { + ArgumentNullException.ThrowIfNull(set); + _set = set; + } + + /// Gets an empty . + public static ReadOnlySet Empty { get; } = new ReadOnlySet(new HashSet()); + + /// Gets the set that is wrapped by this object. + protected ISet Set => _set; + + /// + public int Count => _set.Count; + + /// + public IEnumerator GetEnumerator() => + _set.Count == 0 ? ((IEnumerable)Array.Empty()).GetEnumerator() : + _set.GetEnumerator(); + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + /// + public bool Contains(T item) => _set.Contains(item); + + /// + public bool IsProperSubsetOf(IEnumerable other) => _set.IsProperSubsetOf(other); + + /// + public bool IsProperSupersetOf(IEnumerable other) => _set.IsProperSupersetOf(other); + + /// + public bool IsSubsetOf(IEnumerable other) => _set.IsSubsetOf(other); + + /// + public bool IsSupersetOf(IEnumerable other) => _set.IsSupersetOf(other); + + /// + public bool Overlaps(IEnumerable other) => _set.Overlaps(other); + + /// + public bool SetEquals(IEnumerable other) => _set.SetEquals(other); + + /// + void ICollection.CopyTo(T[] array, int arrayIndex) => _set.CopyTo(array, arrayIndex); + + /// + void ICollection.CopyTo(Array array, int index) => CollectionHelpers.CopyTo(_set, array, index); + + /// + bool ICollection.IsReadOnly => true; + + /// + bool ICollection.IsSynchronized => false; + + /// + object ICollection.SyncRoot => _set is ICollection c ? c.SyncRoot : this; + + /// + bool ISet.Add(T item) => throw new NotSupportedException(); + + /// + void ISet.ExceptWith(IEnumerable other) => throw new NotSupportedException(); + + /// + void ISet.IntersectWith(IEnumerable other) => throw new NotSupportedException(); + + /// + void ISet.SymmetricExceptWith(IEnumerable other) => throw new NotSupportedException(); + + /// + void ISet.UnionWith(IEnumerable other) => throw new NotSupportedException(); + + /// + void ICollection.Add(T item) => throw new NotSupportedException(); + + /// + void ICollection.Clear() => throw new NotSupportedException(); + + /// + bool ICollection.Remove(T item) => throw new NotSupportedException(); + + private static class CollectionHelpers + { + private static void ValidateCopyToArguments(int sourceCount, Array array, int index) + { + ArgumentNullException.ThrowIfNull(array); + + if (array.Rank != 1) + { + throw new ArgumentException("Only single dimensional arrays are supported for the requested action.", nameof(array)); + } + + if (array.GetLowerBound(0) != 0) + { + throw new ArgumentException("The lower bound of target array must be zero.", nameof(array)); + } + + ArgumentOutOfRangeException.ThrowIfNegative(index); + ArgumentOutOfRangeException.ThrowIfGreaterThan(index, array.Length); + + if (array.Length - index < sourceCount) + { + throw new ArgumentException("Destination array is not long enough to copy all the items in the collection. Check array index and length."); + } + } + + internal static void CopyTo(ICollection collection, Array array, int index) + { + ValidateCopyToArguments(collection.Count, array, index); + + if (collection is ICollection nonGenericCollection) + { + // Easy out if the ICollection implements the non-generic ICollection + nonGenericCollection.CopyTo(array, index); + } + else if (array is T[] items) + { + collection.CopyTo(items, index); + } + else + { + // We can't cast array of value type to object[], so we don't support widening of primitive types here. + if (array is not object?[] objects) + { + throw new ArgumentException("Target array type is not compatible with the type of items in the collection.", nameof(array)); + } + + try + { + foreach (T item in collection) + { + objects[index++] = item; + } + } + catch (ArrayTypeMismatchException) + { + throw new ArgumentException("Target array type is not compatible with the type of items in the collection.", nameof(array)); + } + } + } + } +} +#endif diff --git a/src/JsonApiDotNetCore.Annotations/Resources/Annotations/HasManyAttribute.cs b/src/JsonApiDotNetCore.Annotations/Resources/Annotations/HasManyAttribute.cs index 43161f99a8..a906f4a667 100644 --- a/src/JsonApiDotNetCore.Annotations/Resources/Annotations/HasManyAttribute.cs +++ b/src/JsonApiDotNetCore.Annotations/Resources/Annotations/HasManyAttribute.cs @@ -59,7 +59,7 @@ private bool EvaluateIsManyToMany() { if (InverseNavigationProperty != null) { - Type? elementType = CollectionConverter.FindCollectionElementType(InverseNavigationProperty.PropertyType); + Type? elementType = CollectionConverter.Instance.FindCollectionElementType(InverseNavigationProperty.PropertyType); return elementType != null; } @@ -69,7 +69,7 @@ private bool EvaluateIsManyToMany() /// public override void SetValue(object resource, object? newValue) { - ArgumentGuard.NotNull(newValue); + ArgumentNullException.ThrowIfNull(newValue); AssertIsIdentifiableCollection(newValue); base.SetValue(resource, newValue); @@ -99,18 +99,18 @@ private void AssertIsIdentifiableCollection(object newValue) ///
public void AddValue(object resource, IIdentifiable resourceToAdd) { - ArgumentGuard.NotNull(resource); - ArgumentGuard.NotNull(resourceToAdd); + ArgumentNullException.ThrowIfNull(resource); + ArgumentNullException.ThrowIfNull(resourceToAdd); object? rightValue = GetValue(resource); - List rightResources = CollectionConverter.ExtractResources(rightValue).ToList(); + List rightResources = CollectionConverter.Instance.ExtractResources(rightValue).ToList(); if (!rightResources.Exists(nextResource => nextResource == resourceToAdd)) { rightResources.Add(resourceToAdd); Type collectionType = rightValue?.GetType() ?? Property.PropertyType; - IEnumerable typedCollection = CollectionConverter.CopyToTypedCollection(rightResources, collectionType); + IEnumerable typedCollection = CollectionConverter.Instance.CopyToTypedCollection(rightResources, collectionType); base.SetValue(resource, typedCollection); } } diff --git a/src/JsonApiDotNetCore.Annotations/Resources/Annotations/HasOneAttribute.cs b/src/JsonApiDotNetCore.Annotations/Resources/Annotations/HasOneAttribute.cs index 72212c76f2..51d22f9955 100644 --- a/src/JsonApiDotNetCore.Annotations/Resources/Annotations/HasOneAttribute.cs +++ b/src/JsonApiDotNetCore.Annotations/Resources/Annotations/HasOneAttribute.cs @@ -57,7 +57,7 @@ private bool EvaluateIsOneToOne() { if (InverseNavigationProperty != null) { - Type? elementType = CollectionConverter.FindCollectionElementType(InverseNavigationProperty.PropertyType); + Type? elementType = CollectionConverter.Instance.FindCollectionElementType(InverseNavigationProperty.PropertyType); return elementType == null; } diff --git a/src/JsonApiDotNetCore.Annotations/Resources/Annotations/RelationshipAttribute.cs b/src/JsonApiDotNetCore.Annotations/Resources/Annotations/RelationshipAttribute.cs index 492af08c60..21d5bfab1d 100644 --- a/src/JsonApiDotNetCore.Annotations/Resources/Annotations/RelationshipAttribute.cs +++ b/src/JsonApiDotNetCore.Annotations/Resources/Annotations/RelationshipAttribute.cs @@ -12,8 +12,6 @@ namespace JsonApiDotNetCore.Resources.Annotations; [PublicAPI] public abstract class RelationshipAttribute : ResourceFieldAttribute { - private protected static readonly CollectionConverter CollectionConverter = new(); - // This field is definitely assigned after building the resource graph, which is why its public equivalent is declared as non-nullable. private ResourceType? _rightType; @@ -61,7 +59,7 @@ public ResourceType RightType get => _rightType!; internal set { - ArgumentGuard.NotNull(value); + ArgumentNullException.ThrowIfNull(value); _rightType = value; } } diff --git a/src/JsonApiDotNetCore.Annotations/Resources/Annotations/ResourceFieldAttribute.cs b/src/JsonApiDotNetCore.Annotations/Resources/Annotations/ResourceFieldAttribute.cs index 3a3707442c..593b0a905d 100644 --- a/src/JsonApiDotNetCore.Annotations/Resources/Annotations/ResourceFieldAttribute.cs +++ b/src/JsonApiDotNetCore.Annotations/Resources/Annotations/ResourceFieldAttribute.cs @@ -43,7 +43,7 @@ public PropertyInfo Property get => _property!; internal set { - ArgumentGuard.NotNull(value); + ArgumentNullException.ThrowIfNull(value); _property = value; } } @@ -56,7 +56,7 @@ public ResourceType Type get => _type!; internal set { - ArgumentGuard.NotNull(value); + ArgumentNullException.ThrowIfNull(value); _type = value; } } @@ -67,7 +67,7 @@ internal set ///
public object? GetValue(object resource) { - ArgumentGuard.NotNull(resource); + ArgumentNullException.ThrowIfNull(resource); AssertIsIdentifiable(resource); if (Property.GetMethod == null) @@ -93,7 +93,7 @@ internal set ///
public virtual void SetValue(object resource, object? newValue) { - ArgumentGuard.NotNull(resource); + ArgumentNullException.ThrowIfNull(resource); AssertIsIdentifiable(resource); if (Property.SetMethod == null) @@ -115,9 +115,11 @@ public virtual void SetValue(object resource, object? newValue) protected void AssertIsIdentifiable(object? resource) { - if (resource != null && resource is not IIdentifiable) + if (resource is not null and not IIdentifiable) { +#pragma warning disable CA1062 // Validate arguments of public methods throw new InvalidOperationException($"Resource of type '{resource.GetType()}' does not implement {nameof(IIdentifiable)}."); +#pragma warning restore CA1062 // Validate arguments of public methods } } diff --git a/src/JsonApiDotNetCore.Annotations/Resources/RuntimeTypeConverter.cs b/src/JsonApiDotNetCore.Annotations/Resources/RuntimeTypeConverter.cs index 14c35b8e26..74a4eb877c 100644 --- a/src/JsonApiDotNetCore.Annotations/Resources/RuntimeTypeConverter.cs +++ b/src/JsonApiDotNetCore.Annotations/Resources/RuntimeTypeConverter.cs @@ -1,3 +1,4 @@ +using System.Collections.Concurrent; using System.Globalization; using JetBrains.Annotations; @@ -13,6 +14,8 @@ public static class RuntimeTypeConverter { private const string ParseQueryStringsUsingCurrentCultureSwitchName = "JsonApiDotNetCore.ParseQueryStringsUsingCurrentCulture"; + private static readonly ConcurrentDictionary DefaultTypeCache = new(); + /// /// Converts the specified value to the specified type. /// @@ -30,7 +33,7 @@ public static class RuntimeTypeConverter /// public static object? ConvertType(object? value, Type type) { - ArgumentGuard.NotNull(type); + ArgumentNullException.ThrowIfNull(type); // Earlier versions of JsonApiDotNetCore failed to pass CultureInfo.InvariantCulture in the parsing below, which resulted in the 'current' // culture being used. Unlike parsing JSON request/response bodies, this effectively meant that query strings were parsed based on the @@ -137,6 +140,8 @@ public static class RuntimeTypeConverter ///
public static bool CanContainNull(Type type) { + ArgumentNullException.ThrowIfNull(type); + return !type.IsValueType || Nullable.GetUnderlyingType(type) != null; } @@ -148,6 +153,8 @@ public static bool CanContainNull(Type type) /// public static object? GetDefaultValue(Type type) { - return type.IsValueType ? Activator.CreateInstance(type) : null; + ArgumentNullException.ThrowIfNull(type); + + return type.IsValueType ? DefaultTypeCache.GetOrAdd(type, Activator.CreateInstance) : null; } } diff --git a/src/JsonApiDotNetCore.Annotations/TypeExtensions.cs b/src/JsonApiDotNetCore.Annotations/TypeExtensions.cs index 785dff030a..89b8158554 100644 --- a/src/JsonApiDotNetCore.Annotations/TypeExtensions.cs +++ b/src/JsonApiDotNetCore.Annotations/TypeExtensions.cs @@ -15,7 +15,7 @@ public static bool IsOrImplementsInterface(this Type? source) ///
private static bool IsOrImplementsInterface(this Type? source, Type interfaceType) { - ArgumentGuard.NotNull(interfaceType); + ArgumentNullException.ThrowIfNull(interfaceType); if (source == null) { @@ -41,7 +41,7 @@ private static bool AreTypesEqual(Type left, Type right, bool isLeftGeneric) ///
public static string GetFriendlyTypeName(this Type type) { - ArgumentGuard.NotNull(type); + ArgumentNullException.ThrowIfNull(type); // Based on https://stackoverflow.com/questions/2581642/how-do-i-get-the-type-name-of-a-generic-type-argument. diff --git a/src/JsonApiDotNetCore.OpenApi.Client.Kiota/Build/JsonApiDotNetCore.OpenApi.Client.Kiota.props b/src/JsonApiDotNetCore.OpenApi.Client.Kiota/Build/JsonApiDotNetCore.OpenApi.Client.Kiota.props new file mode 100644 index 0000000000..10a3fc585b --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Client.Kiota/Build/JsonApiDotNetCore.OpenApi.Client.Kiota.props @@ -0,0 +1,49 @@ + + + + + --backing-store --exclude-backward-compatible --clean-output --clear-cache --log-level Warning --disable-validation-rules KnownAndNotSupportedFormats,InconsistentTypeFormatPair + + + true + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/JsonApiDotNetCore.OpenApi.Client.Kiota/Build/JsonApiDotNetCore.OpenApi.Client.Kiota.targets b/src/JsonApiDotNetCore.OpenApi.Client.Kiota/Build/JsonApiDotNetCore.OpenApi.Client.Kiota.targets new file mode 100644 index 0000000000..72b32aa7a5 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Client.Kiota/Build/JsonApiDotNetCore.OpenApi.Client.Kiota.targets @@ -0,0 +1,189 @@ + + + + + + + + + (?:\r\n|\n|\r)(#pragma|using)", RegexOptions.Singleline | RegexOptions.Compiled); + private static readonly Regex NullableRegex = new(@"(?s)#if NETSTANDARD2_1_OR_GREATER .*?(?:\r\n|\n|\r)#nullable enable(?:\r\n|\n|\r)(?.*?)(?:\r\n|\n|\r)#nullable restore(?:\r\n|\n|\r)#else(?:\r\n|\n|\r)(?.*?)(?:\r\n|\n|\r)#endif", RegexOptions.Singleline | RegexOptions.Compiled); + private static readonly Regex LineBreaksRegex = new(@"}(?:\r\n|\n|\r)(?[ ]+/// )", RegexOptions.Singleline | RegexOptions.Compiled); + + public string StartDirectory { get; set; } + + public override bool Execute() + { + string absoluteStartDirectory = Path.GetFullPath(StartDirectory); + Log.LogMessage(MessageImportance.High, $"Patching kiota output files in {absoluteStartDirectory}"); + + foreach (string path in Directory.GetFiles(absoluteStartDirectory, "*.cs", SearchOption.AllDirectories)) + { + string content = File.ReadAllText(path); + content = HeaderRegex.Replace(content, $"// {Environment.NewLine}#nullable enable{Environment.NewLine}#pragma warning disable CS8625{Environment.NewLine}$1"); + content = NullableRegex.Replace(content, "$1"); + content = LineBreaksRegex.Replace(content, $"}}{Environment.NewLine}{Environment.NewLine}$1"); + + File.WriteAllText(path, content); + Log.LogMessage(MessageImportance.Normal, $"Patched file: {path}"); + } + + return true; + } + } + ]]> + + + + + + + + + + + + + + %(Arguments) --openapi %(Identity) + + + %(Arguments) --language %(Language) + + + %(Arguments) --language csharp + + + %(Arguments) --class-name %(ClassName) + + + %(Arguments) --namespace-name %(NamespaceName) + + + %(Arguments) --output %(OutputPath) + <_NonEmptyOutputPath>%(OutputPath) + + + <_NonEmptyOutputPath>./output + + + %(Arguments) --log-level %(LogLevel) + + + %(Arguments) --backing-store + + + %(Arguments) --exclude-backward-compatible + + + %(Arguments) --additional-data %(AdditionalData) + + + %(Arguments) --serializer %(Serializer) + + + %(Arguments) --deserializer %(Deserializer) + + + %(Arguments) --clean-output + + + %(Arguments) --clear-cache + + + %(Arguments) --structured-mime-types %(MimeTypes) + + + %(Arguments) --include-path %(IncludePath) + + + %(Arguments) --exclude-path %(ExcludePath) + + + %(Arguments) --disable-validation-rules %(DisableValidationRules) + + + %(Arguments) --disable-ssl-validation + + + %(Arguments) --type-access-modifier %(TypeAccessModifier) + + + %(Arguments) %(ExtraArguments) + + + + + + + + <_WildcardGroup Include="%2A%2A/%2A.cs"> + %(KiotaReference._NonEmptyOutputPath) + + + + + + + + + <_RelativeExcludePathGroup Include="@(_FilesToExcludeGroup)" Condition="'@(_FilesToExcludeGroup)' != ''"> + + $([MSBuild]::MakeRelative($(MSBuildProjectDirectory), %(_FilesToExcludeGroup.FullPath))) + + + + + + + + + + + + <_WildcardGroup Include="%2A%2A/%2A.cs"> + %(KiotaReference._NonEmptyOutputPath) + + + + + + + + + <_RelativeIncludePathGroup Include="@(_FilesToIncludeGroup)"> + + $([MSBuild]::MakeRelative($(MSBuildProjectDirectory), %(_FilesToIncludeGroup.FullPath))) + + + + + + + + + + + + <_KiotaCommand Condition="'$(KiotaAutoRestoreTools)' == 'true'">dotnet kiota generate + <_KiotaCommand Condition="'$(KiotaAutoRestoreTools)' != 'true'">kiota generate + + + + + + + + diff --git a/src/JsonApiDotNetCore.OpenApi.Client.Kiota/JsonApiDotNetCore.OpenApi.Client.Kiota.csproj b/src/JsonApiDotNetCore.OpenApi.Client.Kiota/JsonApiDotNetCore.OpenApi.Client.Kiota.csproj new file mode 100644 index 0000000000..640b949477 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Client.Kiota/JsonApiDotNetCore.OpenApi.Client.Kiota.csproj @@ -0,0 +1,42 @@ + + + net8.0 + true + true + false + $(NoWarn);NU5110;NU5111 + + + + + + $(VersionPrefix)-preview.$(OpenApiPreviewNumber) + jsonapidotnetcore;jsonapi;json:api;dotnet;asp.net;rest;web-api;openapi;swagger;client;kiota + Provides OpenAPI support for JSON:API generated clients using Kiota. + json-api-dotnet + https://www.jsonapi.net/ + MIT + false + See https://github.com/json-api-dotnet/JsonApiDotNetCore/releases. + package-icon.png + PackageReadme.md + true + embedded + + + + + + + + + + + + + + + + + + diff --git a/src/JsonApiDotNetCore.OpenApi.Client.Kiota/SetQueryStringHttpMessageHandler.cs b/src/JsonApiDotNetCore.OpenApi.Client.Kiota/SetQueryStringHttpMessageHandler.cs new file mode 100644 index 0000000000..fd088fb956 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Client.Kiota/SetQueryStringHttpMessageHandler.cs @@ -0,0 +1,57 @@ +using JetBrains.Annotations; +using Microsoft.AspNetCore.WebUtilities; + +namespace JsonApiDotNetCore.OpenApi.Client.Kiota; + +/// +/// Enables setting the HTTP query string. Workaround for https://github.com/microsoft/kiota/issues/3800. +/// +[PublicAPI] +public sealed class SetQueryStringHttpMessageHandler : DelegatingHandler +{ + private IDictionary? _queryString; + + public IDisposable CreateScope(IDictionary queryString) + { + ArgumentNullException.ThrowIfNull(queryString); + + return new QueryStringScope(this, queryString); + } + + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + ArgumentNullException.ThrowIfNull(request); + + if (_queryString is { Count: > 0 } && request.RequestUri != null) + { + request.RequestUri = new Uri(QueryHelpers.AddQueryString(request.RequestUri.ToString(), _queryString)); + } + + return base.SendAsync(request, cancellationToken); + } + + private sealed class QueryStringScope : IDisposable + { + private readonly SetQueryStringHttpMessageHandler _owner; + private readonly IDictionary? _backupQueryString; + + public QueryStringScope(SetQueryStringHttpMessageHandler owner, IDictionary queryString) + { + _owner = owner; + _backupQueryString = owner._queryString; + + owner._queryString = SetEmptyStringForNullValues(queryString); + } + + private static Dictionary SetEmptyStringForNullValues(IDictionary queryString) + { + // QueryHelpers.AddQueryString ignores null values, so replace them with empty strings to get them sent. + return queryString.ToDictionary(pair => pair.Key, pair => pair.Value ?? (string?)string.Empty); + } + + public void Dispose() + { + _owner._queryString = _backupQueryString; + } + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Client.NSwag/ApiException.cs b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/ApiException.cs new file mode 100644 index 0000000000..8b66839e9e --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/ApiException.cs @@ -0,0 +1,24 @@ +using JetBrains.Annotations; + +// We cannot rely on generating ApiException as soon as we are generating multiple clients, see https://github.com/RicoSuter/NSwag/issues/2839#issuecomment-776647377. +// Instead, we configure NSwag to point to the exception below in the generated code. + +namespace JsonApiDotNetCore.OpenApi.Client.NSwag; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public class ApiException(string message, int statusCode, string? response, IReadOnlyDictionary> headers, Exception? innerException) + : Exception($"HTTP {statusCode}: {message}", innerException) +{ + public int StatusCode { get; } = statusCode; + public virtual string? Response { get; } = string.IsNullOrEmpty(response) ? null : response; + public IReadOnlyDictionary> Headers { get; } = headers; +} + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public sealed class ApiException( + string message, int statusCode, string? response, IReadOnlyDictionary> headers, TResult result, Exception? innerException) + : ApiException(message, statusCode, response, headers, innerException) +{ + public TResult Result { get; } = result; + public override string Response => $"The response body is unavailable. Use the {nameof(Result)} property instead."; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Client.NSwag/ApiResponse.cs b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/ApiResponse.cs new file mode 100644 index 0000000000..74ee77127f --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/ApiResponse.cs @@ -0,0 +1,79 @@ +using System.Net; +using JetBrains.Annotations; + +namespace JsonApiDotNetCore.OpenApi.Client.NSwag; + +[PublicAPI] +public class ApiResponse(int statusCode, IReadOnlyDictionary> headers) +{ + public int StatusCode { get; private set; } = statusCode; + public IReadOnlyDictionary> Headers { get; private set; } = headers; + + public static async Task TranslateAsync(Func> operation) + where TResponse : class + { + ArgumentNullException.ThrowIfNull(operation); + + try + { + return await operation().ConfigureAwait(false); + } + catch (ApiException exception) when (exception.StatusCode is (int)HttpStatusCode.NoContent or (int)HttpStatusCode.NotModified) + { + // Workaround for https://github.com/RicoSuter/NSwag/issues/2499 + return null; + } + } + + public static async Task TranslateAsync(Func operation) + { + ArgumentNullException.ThrowIfNull(operation); + + try + { + await operation().ConfigureAwait(false); + } + catch (ApiException exception) when (exception.StatusCode is (int)HttpStatusCode.NoContent or (int)HttpStatusCode.NotModified) + { + // Workaround for https://github.com/RicoSuter/NSwag/issues/2499 + } + } + + public static async Task> TranslateAsync(Func>> operation) + where TResult : class + { + ArgumentNullException.ThrowIfNull(operation); + + try + { + return (await operation().ConfigureAwait(false))!; + } + catch (ApiException exception) when (exception.StatusCode is (int)HttpStatusCode.NoContent or (int)HttpStatusCode.NotModified) + { + // Workaround for https://github.com/RicoSuter/NSwag/issues/2499 + return new ApiResponse(exception.StatusCode, exception.Headers, null); + } + } + + public static async Task TranslateAsync(Func> operation) + { + ArgumentNullException.ThrowIfNull(operation); + + try + { + return await operation().ConfigureAwait(false); + } + catch (ApiException exception) when (exception.StatusCode is (int)HttpStatusCode.NoContent or (int)HttpStatusCode.NotModified) + { + // Workaround for https://github.com/RicoSuter/NSwag/issues/2499 + return new ApiResponse(exception.StatusCode, exception.Headers); + } + } +} + +[PublicAPI] +public class ApiResponse(int statusCode, IReadOnlyDictionary> headers, TResult result) + : ApiResponse(statusCode, headers) +{ + public TResult Result { get; private set; } = result; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Client.NSwag/BlockedJsonInheritanceConverter.cs b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/BlockedJsonInheritanceConverter.cs new file mode 100644 index 0000000000..a3a7e627db --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/BlockedJsonInheritanceConverter.cs @@ -0,0 +1,43 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; + +namespace JsonApiDotNetCore.OpenApi.Client.NSwag; + +// Referenced from liquid template, to ensure the built-in JsonInheritanceConverter from NSwag is never used. +[PublicAPI] +public abstract class BlockedJsonInheritanceConverter : JsonConverter +{ + private const string DefaultDiscriminatorName = "discriminator"; + + public string DiscriminatorName { get; } + + public override bool CanWrite => true; + public override bool CanRead => true; + + protected BlockedJsonInheritanceConverter() + : this(DefaultDiscriminatorName) + { + } + + protected BlockedJsonInheritanceConverter(string discriminatorName) + { + ArgumentException.ThrowIfNullOrEmpty(discriminatorName); + + DiscriminatorName = discriminatorName; + } + + public override bool CanConvert(Type objectType) + { + return true; + } + + public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) + { + throw new InvalidOperationException("JsonInheritanceConverter is incompatible with JSON:API and must not be used."); + } + + public override object ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) + { + throw new InvalidOperationException("JsonInheritanceConverter is incompatible with JSON:API and must not be used."); + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Client.NSwag/Build/JsonApiDotNetCore.OpenApi.Client.NSwag.props b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/Build/JsonApiDotNetCore.OpenApi.Client.NSwag.props new file mode 100644 index 0000000000..cc65a6ac4a --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/Build/JsonApiDotNetCore.OpenApi.Client.NSwag.props @@ -0,0 +1,15 @@ + + + NSwagCSharp + false + false + ApiResponse + JsonApiDotNetCore.OpenApi.Client.NSwag + true + true + true + JsonApiDotNetCore.OpenApi.Client.NSwag.JsonApiClient + Prism + $(MSBuildThisFileDirectory)../Templates + + diff --git a/src/JsonApiDotNetCore.OpenApi.Client.NSwag/IJsonApiClient.cs b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/IJsonApiClient.cs new file mode 100644 index 0000000000..df6a35d78e --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/IJsonApiClient.cs @@ -0,0 +1,41 @@ +using System.Linq.Expressions; +using JetBrains.Annotations; + +namespace JsonApiDotNetCore.OpenApi.Client.NSwag; + +[PublicAPI] +public interface IJsonApiClient +{ + /// + /// Ensures correct serialization of JSON:API attributes in the request body of a POST/PATCH request at a resource endpoint. Properties with default + /// values are omitted, unless explicitly included using + /// + /// In JSON:API, an omitted attribute indicates to ignore it, while an attribute that is set to null means to clear it. This poses a problem, + /// because the serializer cannot distinguish between "you have explicitly set this .NET property to its default value" vs "you didn't touch it, so it + /// contains its default value" when converting to JSON. + /// + /// + /// + /// The request document instance for which default values should be omitted. + /// + /// + /// Optional. A list of lambda expressions that indicate which properties to always include in the JSON request body. For example: + /// video.Title, video => video.Summary + /// ]]> + /// + /// + /// The type of the request document. + /// + /// + /// The type of the attributes object inside . + /// + /// + /// An to clear the current registration. For efficient memory usage, it is recommended to wrap calls to this method in a + /// using statement, so the registrations are cleaned up after executing the request. After disposal, the client can be reused without the + /// registrations added earlier. + /// + IDisposable WithPartialAttributeSerialization(TRequestDocument requestDocument, + params Expression>[] alwaysIncludedAttributeSelectors) + where TRequestDocument : class; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Client.NSwag/JsonApiClient.cs b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/JsonApiClient.cs new file mode 100644 index 0000000000..14cf54825d --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/JsonApiClient.cs @@ -0,0 +1,458 @@ +using System.ComponentModel; +using System.Reflection; +using JetBrains.Annotations; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Serialization; + +namespace JsonApiDotNetCore.OpenApi.Client.NSwag; + +/// +/// Base class to inherit auto-generated NSwag OpenAPI clients from. Provides support for partial POST/PATCH in JSON:API requests, optionally combined +/// with OpenAPI inheritance. +/// +[PublicAPI] +public abstract class JsonApiClient +{ + private const string GeneratedJsonInheritanceConverterName = "JsonInheritanceConverter"; + private static readonly DefaultContractResolver UnmodifiedContractResolver = new(); + + private readonly Dictionary> _propertyStore = []; + + /// + /// Whether to automatically clear tracked properties after sending a request. Default value: true. Set to false to reuse tracked + /// properties for multiple requests and call after the last request to clean up. + /// + public bool AutoClearTracked { get; set; } = true; + + internal void Track(T container) + where T : INotifyPropertyChanged, new() + { + container.PropertyChanged += ContainerOnPropertyChanged; + + MarkAsTracked(container); + } + + private void ContainerOnPropertyChanged(object? sender, PropertyChangedEventArgs args) + { + if (sender is INotifyPropertyChanged container && args.PropertyName != null) + { + MarkAsTracked(container, args.PropertyName); + } + } + + /// + /// Marks the specified properties on an object instance as tracked. Use this when unable to use inline initializer syntax for tracking. + /// + /// + /// The object instance whose properties to mark as tracked. + /// + /// + /// The names of the properties to mark as tracked. Properties in this list are always included. Any other property is only included if its value differs + /// from the property type's default value. + /// + public void MarkAsTracked(INotifyPropertyChanged container, params string[] propertyNames) + { + ArgumentNullException.ThrowIfNull(container); + ArgumentNullException.ThrowIfNull(propertyNames); + + if (!_propertyStore.TryGetValue(container, out ISet? properties)) + { + properties = new HashSet(); + _propertyStore[container] = properties; + } + + foreach (string propertyName in propertyNames) + { + properties.Add(propertyName); + } + } + + /// + /// Clears all tracked properties. Call this after sending multiple requests when is set to false. + /// + public void ClearAllTracked() + { + foreach (INotifyPropertyChanged container in _propertyStore.Keys) + { + container.PropertyChanged -= ContainerOnPropertyChanged; + } + + _propertyStore.Clear(); + } + + private void RemoveContainer(INotifyPropertyChanged container) + { + container.PropertyChanged -= ContainerOnPropertyChanged; + _propertyStore.Remove(container); + } + + /// + /// Initial setup. Call this from the Initialize partial method in the auto-generated NSwag client. + /// + /// + /// The to configure. + /// + /// + /// CAUTION: Calling this method makes the serializer stateful, which removes thread-safety of the owning auto-generated NSwag client. As a result, the + /// client MUST NOT be shared. So don't use a static instance, and don't register as a singleton in the service container. Also, do not execute parallel + /// requests on the same NSwag client instance. Executing multiple sequential requests on the same generated client instance is fine. + /// + protected void SetSerializerSettingsForJsonApi(JsonSerializerSettings serializerSettings) + { + ArgumentNullException.ThrowIfNull(serializerSettings); + + serializerSettings.ContractResolver = new InsertDiscriminatorPropertyContractResolver(); + serializerSettings.Converters.Insert(0, new PropertyTrackingInheritanceConverter(this)); + } + + private static string? GetDiscriminatorName(Type objectType) + { + JsonContract contract = UnmodifiedContractResolver.ResolveContract(objectType); + + if (contract.Converter != null && contract.Converter.GetType().Name == GeneratedJsonInheritanceConverterName) + { + var inheritanceConverter = (BlockedJsonInheritanceConverter)contract.Converter; + return inheritanceConverter.DiscriminatorName; + } + + return null; + } + + /// + /// Replacement for the writing part of client-generated JsonInheritanceConverter that doesn't block other converters and preserves the JSON path on + /// error. + /// + private class InsertDiscriminatorPropertyContractResolver : DefaultContractResolver + { + protected override JsonObjectContract CreateObjectContract(Type objectType) + { + // NSwag adds [JsonConverter(typeof(JsonInheritanceConverter), "type")] on types to write the discriminator. + // This annotation has higher precedence over converters in the serializer settings, which is why ours normally won't execute. + // Once we tell Newtonsoft to ignore JsonInheritanceConverter, our converter can kick in. + + JsonObjectContract contract = base.CreateObjectContract(objectType); + + if (contract.Converter != null && contract.Converter.GetType().Name == GeneratedJsonInheritanceConverterName) + { + contract.Converter = null; + } + + return contract; + } + + protected override IList CreateProperties(Type type, MemberSerialization memberSerialization) + { + IList properties = base.CreateProperties(type, memberSerialization); + + string? discriminatorName = GetDiscriminatorName(type); + + if (discriminatorName != null) + { + JsonProperty discriminatorProperty = CreateDiscriminatorProperty(discriminatorName, type); + properties.Insert(0, discriminatorProperty); + } + + return properties; + } + + private static JsonProperty CreateDiscriminatorProperty(string discriminatorName, Type declaringType) + { + return new JsonProperty + { + PropertyName = discriminatorName, + PropertyType = typeof(string), + DeclaringType = declaringType, + ValueProvider = new DiscriminatorValueProvider(), + Readable = true, + Writable = true + }; + } + + private sealed class DiscriminatorValueProvider : IValueProvider + { + public object? GetValue(object target) + { + Type type = target.GetType(); + + foreach (Attribute attribute in type.GetCustomAttributes(true)) + { + var shim = JsonInheritanceAttributeShim.TryCreate(attribute); + + if (shim != null && shim.Type == type) + { + return shim.Key; + } + } + + return null; + } + + public void SetValue(object target, object? value) + { + // Nothing to do, NSwag doesn't generate a property for the discriminator. + } + } + } + + /// + /// Provides support for writing partial POST/PATCH in JSON:API requests via tracked properties. Provides reading of discriminator for inheritance. + /// + private sealed class PropertyTrackingInheritanceConverter : JsonConverter + { + [ThreadStatic] + private static bool _isWriting; + + [ThreadStatic] + private static bool _isReading; + + private readonly JsonApiClient _apiClient; + + public override bool CanRead + { + get + { + if (_isReading) + { + // Prevent infinite recursion, but auto-reset so we'll participate in nested objects. + _isReading = false; + return false; + } + + return true; + } + } + + public override bool CanWrite + { + get + { + if (_isWriting) + { + // Prevent infinite recursion, but auto-reset so we'll participate in nested objects. + _isWriting = false; + return false; + } + + return true; + } + } + + public PropertyTrackingInheritanceConverter(JsonApiClient apiClient) + { + ArgumentNullException.ThrowIfNull(apiClient); + + _apiClient = apiClient; + } + + public override bool CanConvert(Type objectType) + { + // Because this is called BEFORE CanRead/CanWrite, respond to both tracking and inheritance. + // We don't actually write for inheritance, so bail out later if that's the case. + + if (_apiClient._propertyStore.Keys.Any(containingType => containingType.GetType() == objectType)) + { + return true; + } + + var converterAttribute = objectType.GetCustomAttribute(true); + return converterAttribute is { ConverterType.Name: GeneratedJsonInheritanceConverterName }; + } + + public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) + { + _isReading = true; + + try + { + JToken token = JToken.ReadFrom(reader); + string? discriminatorValue = GetDiscriminatorValue(objectType, token); + + Type resolvedType = ResolveTypeFromDiscriminatorValue(objectType, discriminatorValue); + return token.ToObject(resolvedType, serializer); + } + finally + { + _isReading = false; + } + } + + private static string? GetDiscriminatorValue(Type objectType, JToken token) + { + var jsonConverterAttribute = objectType.GetCustomAttribute(true)!; + + if (jsonConverterAttribute.ConverterParameters is not [string]) + { + throw new JsonException($"Expected single 'type' parameter for JsonInheritanceConverter usage on type '{objectType}'."); + } + + string discriminatorName = (string)jsonConverterAttribute.ConverterParameters[0]; + return token.Children().FirstOrDefault(property => property.Name == discriminatorName)?.Value.ToString(); + } + + private static Type ResolveTypeFromDiscriminatorValue(Type objectType, string? discriminatorValue) + { + if (discriminatorValue != null) + { + foreach (Attribute attribute in objectType.GetCustomAttributes(true)) + { + var shim = JsonInheritanceAttributeShim.TryCreate(attribute); + + if (shim != null && shim.Key == discriminatorValue) + { + return shim.Type; + } + } + } + + return objectType; + } + + public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) + { + _isWriting = true; + + try + { + if (value is INotifyPropertyChanged container && _apiClient._propertyStore.TryGetValue(container, out ISet? properties)) + { + // Because we're overwriting NullValueHandling/DefaultValueHandling, we miss out on some validations that Newtonsoft would otherwise run. + AssertRequiredTrackedPropertiesHaveNoDefaultValue(container, properties, writer.Path); + + IContractResolver backupContractResolver = serializer.ContractResolver; + + try + { + // Caution: Swapping the contract resolver is not safe for concurrent usage, yet it needs to know the tracked instance. + serializer.ContractResolver = new PropertyTrackingContractResolver(container, properties); + serializer.Serialize(writer, value); + + if (_apiClient.AutoClearTracked) + { + _apiClient.RemoveContainer(container); + } + } + finally + { + serializer.ContractResolver = backupContractResolver; + } + } + else + { + // We get here when the type is tracked, but not this instance. Or when writing for inheritance. + serializer.Serialize(writer, value); + } + } + finally + { + _isWriting = false; + } + } + + private static void AssertRequiredTrackedPropertiesHaveNoDefaultValue(object container, ISet properties, string jsonPath) + { + foreach (PropertyInfo propertyInfo in container.GetType().GetProperties()) + { + bool isTracked = properties.Contains(propertyInfo.Name); + + if (!isTracked) + { + AssertPropertyHasNonDefaultValueIfRequired(container, propertyInfo, jsonPath); + } + } + } + + private static void AssertPropertyHasNonDefaultValueIfRequired(object attributesObject, PropertyInfo propertyInfo, string jsonPath) + { + var jsonProperty = propertyInfo.GetCustomAttribute(); + + if (jsonProperty is { Required: Required.Always or Required.AllowNull }) + { + if (PropertyHasDefaultValue(propertyInfo, attributesObject)) + { + throw new JsonSerializationException( + $"Cannot write a default value for property '{jsonProperty.PropertyName}'. Property requires a non-default value. Path '{jsonPath}'.", + jsonPath, 0, 0, null); + } + } + } + + private static bool PropertyHasDefaultValue(PropertyInfo propertyInfo, object instance) + { + object? propertyValue = propertyInfo.GetValue(instance); + object? defaultValue = GetDefaultValue(propertyInfo.PropertyType); + + return EqualityComparer.Default.Equals(propertyValue, defaultValue); + } + + private static object? GetDefaultValue(Type type) + { + return type.IsValueType ? Activator.CreateInstance(type) : null; + } + } + + /// + /// Overrules the and annotations on generated properties for tracked object + /// instances to support JSON:API partial POST/PATCH. + /// + private sealed class PropertyTrackingContractResolver : InsertDiscriminatorPropertyContractResolver + { + private readonly INotifyPropertyChanged _container; + private readonly ISet _properties; + + public PropertyTrackingContractResolver(INotifyPropertyChanged container, ISet properties) + { + ArgumentNullException.ThrowIfNull(container); + ArgumentNullException.ThrowIfNull(properties); + + _container = container; + _properties = properties; + } + + protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) + { + JsonProperty jsonProperty = base.CreateProperty(member, memberSerialization); + + if (jsonProperty.DeclaringType == _container.GetType()) + { + if (_properties.Contains(jsonProperty.UnderlyingName!)) + { + jsonProperty.NullValueHandling = NullValueHandling.Include; + jsonProperty.DefaultValueHandling = DefaultValueHandling.Include; + } + else + { + jsonProperty.NullValueHandling = NullValueHandling.Ignore; + jsonProperty.DefaultValueHandling = DefaultValueHandling.Ignore; + } + } + + return jsonProperty; + } + } + + private sealed class JsonInheritanceAttributeShim + { + private readonly Attribute _instance; + private readonly PropertyInfo _keyProperty; + private readonly PropertyInfo _typeProperty; + + public string Key => (string)_keyProperty.GetValue(_instance)!; + public Type Type => (Type)_typeProperty.GetValue(_instance)!; + + private JsonInheritanceAttributeShim(Attribute instance, Type type) + { + _instance = instance; + _keyProperty = type.GetProperty("Key") ?? throw new ArgumentException("Key property not found.", nameof(instance)); + _typeProperty = type.GetProperty("Type") ?? throw new ArgumentException("Type property not found.", nameof(instance)); + } + + public static JsonInheritanceAttributeShim? TryCreate(Attribute attribute) + { + ArgumentNullException.ThrowIfNull(attribute); + + Type type = attribute.GetType(); + return type.Name == "JsonInheritanceAttribute" ? new JsonInheritanceAttributeShim(attribute, type) : null; + } + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Client.NSwag/JsonApiDotNetCore.OpenApi.Client.NSwag.csproj b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/JsonApiDotNetCore.OpenApi.Client.NSwag.csproj new file mode 100644 index 0000000000..20e2306730 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/JsonApiDotNetCore.OpenApi.Client.NSwag.csproj @@ -0,0 +1,37 @@ + + + net8.0 + true + true + false + + + + + + $(VersionPrefix)-preview.$(OpenApiPreviewNumber) + jsonapidotnetcore;jsonapi;json:api;dotnet;asp.net;rest;web-api;openapi;swagger;client;nswag + Provides OpenAPI support for JSON:API generated clients using NSwag. + json-api-dotnet + https://www.jsonapi.net/ + MIT + false + See https://github.com/json-api-dotnet/JsonApiDotNetCore/releases. + package-icon.png + PackageReadme.md + true + embedded + + + + + + + + + + + + + + diff --git a/src/JsonApiDotNetCore.OpenApi.Client.NSwag/NotifyPropertySet.cs b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/NotifyPropertySet.cs new file mode 100644 index 0000000000..80adb56477 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/NotifyPropertySet.cs @@ -0,0 +1,72 @@ +using System.ComponentModel; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; + +// Adapted from https://github.com/PrismLibrary/Prism/blob/9.0.537/src/Prism.Core/Mvvm/BindableBase.cs for JsonApiDotNetCore. + +#pragma warning disable AV1553 // Do not use optional parameters with default value null for strings, collections or tasks +#pragma warning disable AV1554 // Method contains optional parameter in type hierarchy +#pragma warning disable AV1562 // Do not declare a parameter as ref or out + +namespace JsonApiDotNetCore.OpenApi.Client.NSwag; + +/// +/// Implementation of that doesn't detect changes. +/// +[PublicAPI] +public abstract class NotifyPropertySet : INotifyPropertyChanged +{ + /// + /// Occurs when a property is set. + /// + public event PropertyChangedEventHandler? PropertyChanged; + + /// + /// Sets the property and notifies listeners. + /// + /// + /// Type of the property. + /// + /// + /// Reference to a property with both getter and setter. + /// + /// + /// Desired value for the property. + /// + /// + /// Name of the property used to notify listeners. This value is optional and can be provided automatically when invoked from compilers that support + /// CallerMemberName. + /// + /// + /// Always true. + /// + protected virtual bool SetProperty(ref T storage, T value, [CallerMemberName] string? propertyName = null) + { + storage = value; + RaisePropertyChanged(propertyName); + return true; + } + + /// + /// Raises this object's PropertyChanged event. + /// + /// + /// Name of the property used to notify listeners. This value is optional and can be provided automatically when invoked from compilers that support + /// . + /// + protected void RaisePropertyChanged([CallerMemberName] string? propertyName = null) + { + OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); + } + + /// + /// Raises this object's PropertyChanged event. + /// + /// + /// The . + /// + protected virtual void OnPropertyChanged(PropertyChangedEventArgs args) + { + PropertyChanged?.Invoke(this, args); + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Client.NSwag/Properties/AssemblyInfo.cs b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..1ac53bb335 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("OpenApiNSwagClientTests")] diff --git a/src/JsonApiDotNetCore.OpenApi.Client.NSwag/Templates/Class.Inheritance.liquid b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/Templates/Class.Inheritance.liquid new file mode 100644 index 0000000000..1ddffc4af0 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/Templates/Class.Inheritance.liquid @@ -0,0 +1,14 @@ +{% comment %} + + Adapted from https://github.com/RicoSuter/NJsonSchema/blob/v11.1.0/src/NJsonSchema.CodeGeneration.CSharp/Templates/Class.Inheritance.liquid + for JsonApiDotNetCore, to intercept when properties are set. This is needed to support partial POST/PATCH to distinguish between sending + a property with its default value versus omitting the property. + +{% endcomment %} +{%- if RenderInpc %} +{% if HasInheritance %} : {{ BaseClassName }}{% else %} : System.ComponentModel.INotifyPropertyChanged{% endif %} +{%- elsif RenderPrism %} +{% if HasInheritance %} : {{ BaseClassName }}{% else %} : JsonApiDotNetCore.OpenApi.Client.NSwag.NotifyPropertySet{% endif %} +{%- else %} +{% if HasInheritance %} : {{ BaseClassName }}{% endif %} +{%- endif %} diff --git a/src/JsonApiDotNetCore.OpenApi.Client.NSwag/Templates/Client.Class.Annotations.liquid b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/Templates/Client.Class.Annotations.liquid new file mode 100644 index 0000000000..bf791d968b --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/Templates/Client.Class.Annotations.liquid @@ -0,0 +1,14 @@ +{% comment %} + + Adapted from https://github.com/RicoSuter/NSwag/blob/v14.2.0/src/NSwag.CodeGeneration.CSharp/Templates/Client.Class.Annotations.liquid + for JsonApiDotNetCore, to initialize the JSON serializer for use with JSON:API. + +{% endcomment %} +partial class {{ Class }} +{ + partial void Initialize() + { + _instanceSettings = new Newtonsoft.Json.JsonSerializerSettings(_settings.Value); + SetSerializerSettingsForJsonApi(_instanceSettings); + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Client.NSwag/Templates/JsonInheritanceConverter.liquid b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/Templates/JsonInheritanceConverter.liquid new file mode 100644 index 0000000000..e524f3e1f7 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/Templates/JsonInheritanceConverter.liquid @@ -0,0 +1,19 @@ +{% comment %} + + Adapted from https://github.com/RicoSuter/NJsonSchema/blob/v11.1.0/src/NJsonSchema.CodeGeneration.CSharp/Templates/JsonInheritanceConverter.liquid + for JsonApiDotNetCore, to provide alternate OpenAPI inheritance implementation that enables the use of third-party converters. + +{% endcomment %} +[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "{{ ToolchainVersion }}")] +public class JsonInheritanceConverter : JsonApiDotNetCore.OpenApi.Client.NSwag.BlockedJsonInheritanceConverter +{ + public JsonInheritanceConverter() + : base() + { + } + + public JsonInheritanceConverter(string discriminatorName) + : base(discriminatorName) + { + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Client.NSwag/TrackChangesFor.cs b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/TrackChangesFor.cs new file mode 100644 index 0000000000..278b10ceac --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/TrackChangesFor.cs @@ -0,0 +1,23 @@ +using System.ComponentModel; + +namespace JsonApiDotNetCore.OpenApi.Client.NSwag; + +/// +/// Tracks assignment of property values, to support JSON:API partial POST/PATCH. +/// +/// +/// The type whose property assignments to track. +/// +public sealed class TrackChangesFor + where T : INotifyPropertyChanged, new() +{ + public T Initializer { get; } + + public TrackChangesFor(JsonApiClient apiClient) + { + ArgumentNullException.ThrowIfNull(apiClient); + + Initializer = new T(); + apiClient.Track(Initializer); + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ActionDescriptorExtensions.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ActionDescriptorExtensions.cs new file mode 100644 index 0000000000..1892aca576 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ActionDescriptorExtensions.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using Microsoft.AspNetCore.Mvc.Abstractions; +using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.AspNetCore.Mvc.ModelBinding; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +internal static class ActionDescriptorExtensions +{ + public static MethodInfo GetActionMethod(this ActionDescriptor descriptor) + { + ArgumentNullException.ThrowIfNull(descriptor); + + return ((ControllerActionDescriptor)descriptor).MethodInfo; + } + + public static TFilterMetaData? GetFilterMetadata(this ActionDescriptor descriptor) + where TFilterMetaData : IFilterMetadata + { + ArgumentNullException.ThrowIfNull(descriptor); + + return descriptor.FilterDescriptors.Select(filterDescriptor => filterDescriptor.Filter).OfType().FirstOrDefault(); + } + + public static ControllerParameterDescriptor? GetBodyParameterDescriptor(this ActionDescriptor descriptor) + { + ArgumentNullException.ThrowIfNull(descriptor); + + return (ControllerParameterDescriptor?)descriptor.Parameters.FirstOrDefault(parameterDescriptor => + parameterDescriptor.BindingInfo?.BindingSource == BindingSource.Body); + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ConfigureMvcOptions.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ConfigureMvcOptions.cs new file mode 100644 index 0000000000..e1e04a2464 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ConfigureMvcOptions.cs @@ -0,0 +1,50 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Middleware; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +internal sealed class ConfigureMvcOptions : IConfigureOptions +{ + private readonly IJsonApiRoutingConvention _jsonApiRoutingConvention; + private readonly OpenApiEndpointConvention _openApiEndpointConvention; + private readonly JsonApiRequestFormatMetadataProvider _jsonApiRequestFormatMetadataProvider; + private readonly IJsonApiOptions _jsonApiOptions; + + public ConfigureMvcOptions(IJsonApiRoutingConvention jsonApiRoutingConvention, OpenApiEndpointConvention openApiEndpointConvention, + JsonApiRequestFormatMetadataProvider jsonApiRequestFormatMetadataProvider, IJsonApiOptions jsonApiOptions) + { + ArgumentNullException.ThrowIfNull(jsonApiRoutingConvention); + ArgumentNullException.ThrowIfNull(openApiEndpointConvention); + ArgumentNullException.ThrowIfNull(jsonApiRequestFormatMetadataProvider); + ArgumentNullException.ThrowIfNull(jsonApiOptions); + + _jsonApiRoutingConvention = jsonApiRoutingConvention; + _openApiEndpointConvention = openApiEndpointConvention; + _jsonApiRequestFormatMetadataProvider = jsonApiRequestFormatMetadataProvider; + _jsonApiOptions = jsonApiOptions; + } + + public void Configure(MvcOptions options) + { + ArgumentNullException.ThrowIfNull(options); + + AddSwashbuckleCliCompatibility(options); + + options.InputFormatters.Add(_jsonApiRequestFormatMetadataProvider); + options.Conventions.Add(_openApiEndpointConvention); + + ((JsonApiOptions)_jsonApiOptions).IncludeExtensions(OpenApiMediaTypeExtension.OpenApi, OpenApiMediaTypeExtension.RelaxedOpenApi); + } + + private void AddSwashbuckleCliCompatibility(MvcOptions options) + { + if (!options.Conventions.Any(convention => convention is IJsonApiRoutingConvention)) + { + // See https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/1957 for why this is needed. + options.Conventions.Insert(0, _jsonApiRoutingConvention); + } + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ConfigureSwaggerGenOptions.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ConfigureSwaggerGenOptions.cs new file mode 100644 index 0000000000..f3fb5198ca --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ConfigureSwaggerGenOptions.cs @@ -0,0 +1,152 @@ +using System.Reflection; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.AtomicOperations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; +using JsonApiDotNetCore.Resources; +using Microsoft.AspNetCore.Mvc.ApiExplorer; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +internal sealed class ConfigureSwaggerGenOptions : IConfigureOptions +{ + private static readonly Dictionary BaseToDerivedSchemaTypes = new() + { + [typeof(IdentifierInRequest)] = typeof(IdentifierInRequest<>), + [typeof(ResourceInCreateRequest)] = typeof(DataInCreateRequest<>), + [typeof(ResourceInUpdateRequest)] = typeof(DataInUpdateRequest<>), + [typeof(ResourceInResponse)] = typeof(DataInResponse<>) + }; + + private static readonly Type[] AtomicOperationDerivedSchemaTypes = + [ + typeof(CreateOperation<>), + typeof(UpdateOperation<>), + typeof(DeleteOperation<>), + typeof(UpdateToOneRelationshipOperation<>), + typeof(UpdateToManyRelationshipOperation<>), + typeof(AddToRelationshipOperation<>), + typeof(RemoveFromRelationshipOperation<>) + ]; + + private readonly OpenApiOperationIdSelector _operationIdSelector; + private readonly JsonApiSchemaIdSelector _schemaIdSelector; + private readonly IControllerResourceMapping _controllerResourceMapping; + private readonly IResourceGraph _resourceGraph; + + public ConfigureSwaggerGenOptions(OpenApiOperationIdSelector operationIdSelector, JsonApiSchemaIdSelector schemaIdSelector, + IControllerResourceMapping controllerResourceMapping, IResourceGraph resourceGraph) + { + ArgumentNullException.ThrowIfNull(operationIdSelector); + ArgumentNullException.ThrowIfNull(schemaIdSelector); + ArgumentNullException.ThrowIfNull(controllerResourceMapping); + ArgumentNullException.ThrowIfNull(resourceGraph); + + _operationIdSelector = operationIdSelector; + _schemaIdSelector = schemaIdSelector; + _controllerResourceMapping = controllerResourceMapping; + _resourceGraph = resourceGraph; + } + + public void Configure(SwaggerGenOptions options) + { + ArgumentNullException.ThrowIfNull(options); + + options.SupportNonNullableReferenceTypes(); + options.UseAllOfToExtendReferenceSchemas(); + + options.UseAllOfForInheritance(); + options.SelectDiscriminatorNameUsing(_ => JsonApiPropertyName.Type); + options.SelectDiscriminatorValueUsing(clrType => _resourceGraph.GetResourceType(clrType).PublicName); + options.SelectSubTypesUsing(SelectDerivedTypes); + + options.TagActionsBy(description => GetOpenApiOperationTags(description, _controllerResourceMapping)); + options.CustomOperationIds(_operationIdSelector.GetOpenApiOperationId); + options.CustomSchemaIds(_schemaIdSelector.GetSchemaId); + + options.OperationFilter(); + options.DocumentFilter(); + options.DocumentFilter(); + options.DocumentFilter(); + options.DocumentFilter(); + options.DocumentFilter(); + } + + private List SelectDerivedTypes(Type baseType) + { + if (BaseToDerivedSchemaTypes.TryGetValue(baseType, out Type? schemaOpenType)) + { + return GetConstructedTypesFromResourceGraph(schemaOpenType); + } + + if (baseType == typeof(AtomicOperation)) + { + return GetConstructedTypesForAtomicOperation(); + } + + if (baseType.IsAssignableTo(typeof(IIdentifiable))) + { + ResourceType? resourceType = _resourceGraph.FindResourceType(baseType); + + if (resourceType != null && resourceType.IsPartOfTypeHierarchy()) + { + return GetResourceDerivedTypes(resourceType); + } + } + + return []; + } + + private List GetConstructedTypesFromResourceGraph(Type schemaOpenType) + { + List constructedTypes = []; + + foreach (ResourceType resourceType in _resourceGraph.GetResourceTypes()) + { + Type constructedType = schemaOpenType.MakeGenericType(resourceType.ClrType); + constructedTypes.Add(constructedType); + } + + return constructedTypes; + } + + private List GetConstructedTypesForAtomicOperation() + { + List derivedTypes = []; + + foreach (ResourceType resourceType in _resourceGraph.GetResourceTypes()) + { + derivedTypes.AddRange(AtomicOperationDerivedSchemaTypes.Select(openType => openType.MakeGenericType(resourceType.ClrType))); + } + + return derivedTypes; + } + + private static List GetResourceDerivedTypes(ResourceType baseType) + { + List clrTypes = []; + IncludeDerivedTypes(baseType, clrTypes); + return clrTypes; + } + + private static void IncludeDerivedTypes(ResourceType baseType, List clrTypes) + { + foreach (ResourceType derivedType in baseType.DirectlyDerivedTypes) + { + clrTypes.Add(derivedType.ClrType); + IncludeDerivedTypes(derivedType, clrTypes); + } + } + + private static List GetOpenApiOperationTags(ApiDescription description, IControllerResourceMapping controllerResourceMapping) + { + MethodInfo actionMethod = description.ActionDescriptor.GetActionMethod(); + ResourceType? resourceType = controllerResourceMapping.GetResourceTypeForController(actionMethod.ReflectedType); + + return resourceType == null ? ["operations"] : [resourceType.PublicName]; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ConsistencyGuard.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ConsistencyGuard.cs new file mode 100644 index 0000000000..a5ab4f69f5 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ConsistencyGuard.cs @@ -0,0 +1,18 @@ +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +#pragma warning disable AV1008 // Class should not be static + +internal static class ConsistencyGuard +{ + [ExcludeFromCodeCoverage] + public static void ThrowIf([DoesNotReturnIf(true)] bool condition) + { + if (condition) + { + throw new UnreachableException(); + } + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/IJsonApiRequestAccessor.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/IJsonApiRequestAccessor.cs new file mode 100644 index 0000000000..ab9445b39e --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/IJsonApiRequestAccessor.cs @@ -0,0 +1,14 @@ +using JsonApiDotNetCore.Middleware; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +/// +/// Provides access to the current , if one is available. +/// +internal interface IJsonApiRequestAccessor +{ + /// + /// Gets the current . Returns null if there is no active request. + /// + IJsonApiRequest? Current { get; } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ISchemaGenerationTraceScope.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ISchemaGenerationTraceScope.cs new file mode 100644 index 0000000000..e9cb25c7ef --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ISchemaGenerationTraceScope.cs @@ -0,0 +1,6 @@ +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +internal interface ISchemaGenerationTraceScope : IDisposable +{ + void TraceSucceeded(string schemaId); +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/IncludeDependencyScanner.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/IncludeDependencyScanner.cs new file mode 100644 index 0000000000..97f86e2834 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/IncludeDependencyScanner.cs @@ -0,0 +1,53 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Resources.Annotations; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +internal sealed class IncludeDependencyScanner +{ + public static IncludeDependencyScanner Instance { get; } = new(); + + private IncludeDependencyScanner() + { + } + + /// + /// Returns all related resource types that are reachable from the specified resource type. Does not include itself. + /// + public IReadOnlySet GetReachableRelatedTypes(ResourceType resourceType) + { + ArgumentNullException.ThrowIfNull(resourceType); + + HashSet resourceTypesFound = []; + + IncludeResourceType(resourceType, resourceTypesFound); + resourceTypesFound.Remove(resourceType); + + return resourceTypesFound; + } + + private static void IncludeResourceType(ResourceType resourceType, ISet resourceTypesFound) + { + if (resourceTypesFound.Add(resourceType)) + { + IncludeDerivedTypes(resourceType, resourceTypesFound); + IncludeRelatedTypes(resourceType, resourceTypesFound); + } + } + + private static void IncludeDerivedTypes(ResourceType resourceType, ISet resourceTypesFound) + { + foreach (ResourceType derivedType in resourceType.DirectlyDerivedTypes) + { + IncludeResourceType(derivedType, resourceTypesFound); + } + } + + private static void IncludeRelatedTypes(ResourceType resourceType, ISet resourceTypesFound) + { + foreach (RelationshipAttribute relationship in resourceType.Relationships) + { + IncludeResourceType(relationship.RightType, resourceTypesFound); + } + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiActionDescriptorCollectionProvider.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiActionDescriptorCollectionProvider.cs new file mode 100644 index 0000000000..6d63a540cd --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiActionDescriptorCollectionProvider.cs @@ -0,0 +1,225 @@ +using System.Reflection; +using JsonApiDotNetCore.Errors; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Abstractions; +using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.AspNetCore.Mvc.Infrastructure; +using Microsoft.AspNetCore.Mvc.Routing; +using Microsoft.Net.Http.Headers; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +/// +/// Adds JsonApiDotNetCore metadata to s if available. This translates to updating response types in +/// and performing an expansion for secondary and relationship endpoints. For example: +/// /article/{id}/author, /article/{id}/revisions, etc. +/// ]]> +/// +internal sealed class JsonApiActionDescriptorCollectionProvider : IActionDescriptorCollectionProvider +{ + private static readonly string DefaultMediaType = JsonApiMediaType.Default.ToString(); + + private readonly IActionDescriptorCollectionProvider _defaultProvider; + private readonly JsonApiEndpointMetadataProvider _jsonApiEndpointMetadataProvider; + + public ActionDescriptorCollection ActionDescriptors => GetActionDescriptors(); + + public JsonApiActionDescriptorCollectionProvider(IActionDescriptorCollectionProvider defaultProvider, + JsonApiEndpointMetadataProvider jsonApiEndpointMetadataProvider) + { + ArgumentNullException.ThrowIfNull(defaultProvider); + ArgumentNullException.ThrowIfNull(jsonApiEndpointMetadataProvider); + + _defaultProvider = defaultProvider; + _jsonApiEndpointMetadataProvider = jsonApiEndpointMetadataProvider; + } + + private ActionDescriptorCollection GetActionDescriptors() + { + List newDescriptors = _defaultProvider.ActionDescriptors.Items.ToList(); + ActionDescriptor[] endpoints = newDescriptors.Where(IsVisibleJsonApiEndpoint).ToArray(); + + foreach (ActionDescriptor endpoint in endpoints) + { + MethodInfo actionMethod = endpoint.GetActionMethod(); + JsonApiEndpointMetadataContainer endpointMetadataContainer = _jsonApiEndpointMetadataProvider.Get(actionMethod); + + List replacementDescriptorsForEndpoint = + [ + .. AddJsonApiMetadataToAction(endpoint, endpointMetadataContainer.RequestMetadata), + .. AddJsonApiMetadataToAction(endpoint, endpointMetadataContainer.ResponseMetadata) + ]; + + if (replacementDescriptorsForEndpoint.Count > 0) + { + newDescriptors.InsertRange(newDescriptors.IndexOf(endpoint), replacementDescriptorsForEndpoint); + newDescriptors.Remove(endpoint); + } + } + + int descriptorVersion = _defaultProvider.ActionDescriptors.Version; + return new ActionDescriptorCollection(newDescriptors.AsReadOnly(), descriptorVersion); + } + + internal static bool IsVisibleJsonApiEndpoint(ActionDescriptor descriptor) + { + // Only if in a convention ApiExplorer.IsVisible was set to false, the ApiDescriptionActionData will not be present. + return descriptor is ControllerActionDescriptor controllerAction && controllerAction.Properties.ContainsKey(typeof(ApiDescriptionActionData)); + } + + private static List AddJsonApiMetadataToAction(ActionDescriptor endpoint, IJsonApiEndpointMetadata? jsonApiEndpointMetadata) + { + switch (jsonApiEndpointMetadata) + { + case PrimaryResponseMetadata primaryMetadata: + { + UpdateProducesResponseTypeAttribute(endpoint, primaryMetadata.DocumentType); + return []; + } + case PrimaryRequestMetadata primaryMetadata: + { + UpdateBodyParameterDescriptor(endpoint, primaryMetadata.DocumentType, null); + return []; + } + case NonPrimaryEndpointMetadata nonPrimaryEndpointMetadata and (RelationshipResponseMetadata or SecondaryResponseMetadata): + { + return Expand(endpoint, nonPrimaryEndpointMetadata, + (expandedEndpoint, documentType, _) => UpdateProducesResponseTypeAttribute(expandedEndpoint, documentType)); + } + case NonPrimaryEndpointMetadata nonPrimaryEndpointMetadata and RelationshipRequestMetadata: + { + return Expand(endpoint, nonPrimaryEndpointMetadata, UpdateBodyParameterDescriptor); + } + case AtomicOperationsRequestMetadata: + { + UpdateBodyParameterDescriptor(endpoint, typeof(OperationsRequestDocument), null); + return []; + } + case AtomicOperationsResponseMetadata: + { + UpdateProducesResponseTypeAttribute(endpoint, typeof(OperationsResponseDocument)); + return []; + } + default: + { + return []; + } + } + } + + private static void UpdateProducesResponseTypeAttribute(ActionDescriptor endpoint, Type responseDocumentType) + { + ProducesResponseTypeAttribute? attribute = null; + + if (ProducesJsonApiResponseDocument(endpoint)) + { + var producesResponse = endpoint.GetFilterMetadata(); + + if (producesResponse != null) + { + attribute = producesResponse; + } + } + + ConsistencyGuard.ThrowIf(attribute == null); + attribute.Type = responseDocumentType; + } + + private static bool ProducesJsonApiResponseDocument(ActionDescriptor endpoint) + { + var produces = endpoint.GetFilterMetadata(); + + if (produces != null) + { + foreach (string contentType in produces.ContentTypes) + { + if (MediaTypeHeaderValue.TryParse(contentType, out MediaTypeHeaderValue? headerValue)) + { + if (headerValue.MediaType.Equals(DefaultMediaType, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + } + } + + return false; + } + + private static List Expand(ActionDescriptor genericEndpoint, NonPrimaryEndpointMetadata metadata, + Action expansionCallback) + { + List expansion = []; + + foreach ((string relationshipName, Type documentType) in metadata.DocumentTypesByRelationshipName) + { + if (genericEndpoint.AttributeRouteInfo == null) + { + throw new NotSupportedException("Only attribute routing is supported for JsonApiDotNetCore endpoints."); + } + + ActionDescriptor expandedEndpoint = Clone(genericEndpoint); + + RemovePathParameter(expandedEndpoint.Parameters, "relationshipName"); + + ExpandTemplate(expandedEndpoint.AttributeRouteInfo!, relationshipName); + + expansionCallback(expandedEndpoint, documentType, relationshipName); + + expansion.Add(expandedEndpoint); + } + + return expansion; + } + + private static void UpdateBodyParameterDescriptor(ActionDescriptor endpoint, Type documentType, string? parameterName) + { + ControllerParameterDescriptor? requestBodyDescriptor = endpoint.GetBodyParameterDescriptor(); + + if (requestBodyDescriptor == null) + { + MethodInfo actionMethod = endpoint.GetActionMethod(); + + throw new InvalidConfigurationException( + $"The action method '{actionMethod}' on type '{actionMethod.ReflectedType?.FullName}' contains no parameter with a [FromBody] attribute."); + } + + requestBodyDescriptor.ParameterType = documentType; + requestBodyDescriptor.ParameterInfo = new ParameterInfoWrapper(requestBodyDescriptor.ParameterInfo, documentType, parameterName); + } + + private static ActionDescriptor Clone(ActionDescriptor descriptor) + { + ActionDescriptor clone = descriptor.MemberwiseClone(); + clone.AttributeRouteInfo = descriptor.AttributeRouteInfo!.MemberwiseClone(); + clone.FilterDescriptors = descriptor.FilterDescriptors.Select(Clone).ToList(); + clone.Parameters = descriptor.Parameters.Select(parameter => parameter.MemberwiseClone()).ToList(); + return clone; + } + + private static FilterDescriptor Clone(FilterDescriptor descriptor) + { + IFilterMetadata clone = descriptor.Filter.MemberwiseClone(); + + return new FilterDescriptor(clone, descriptor.Scope) + { + Order = descriptor.Order + }; + } + + private static void RemovePathParameter(ICollection parameters, string parameterName) + { + ParameterDescriptor descriptor = parameters.Single(parameterDescriptor => parameterDescriptor.Name == parameterName); + parameters.Remove(descriptor); + } + + private static void ExpandTemplate(AttributeRouteInfo route, string expansionParameter) + { + route.Template = route.Template!.Replace("{relationshipName}", expansionParameter); + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiDotNetCore.OpenApi.Swashbuckle.csproj b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiDotNetCore.OpenApi.Swashbuckle.csproj new file mode 100644 index 0000000000..89822ff4b3 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiDotNetCore.OpenApi.Swashbuckle.csproj @@ -0,0 +1,39 @@ + + + net8.0 + true + true + false + + + + + + $(VersionPrefix)-preview.$(OpenApiPreviewNumber) + jsonapidotnetcore;jsonapi;json:api;dotnet;asp.net;rest;web-api;openapi;swagger;swaggerui;swashbuckle + A Swashbuckle integration that enables you to describe a JsonApiDotNetCore API with an OpenAPI specification. + json-api-dotnet + https://www.jsonapi.net/ + MIT + false + See https://github.com/json-api-dotnet/JsonApiDotNetCore/releases. + package-icon.png + PackageReadme.md + true + embedded + + + + + + + + + + + + + + + + diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/AtomicOperationsRequestMetadata.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/AtomicOperationsRequestMetadata.cs new file mode 100644 index 0000000000..b9b0f44462 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/AtomicOperationsRequestMetadata.cs @@ -0,0 +1,10 @@ +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata; + +internal sealed class AtomicOperationsRequestMetadata : IJsonApiRequestMetadata +{ + public static AtomicOperationsRequestMetadata Instance { get; } = new(); + + private AtomicOperationsRequestMetadata() + { + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/AtomicOperationsResponseMetadata.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/AtomicOperationsResponseMetadata.cs new file mode 100644 index 0000000000..838055c378 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/AtomicOperationsResponseMetadata.cs @@ -0,0 +1,10 @@ +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata; + +internal sealed class AtomicOperationsResponseMetadata : IJsonApiResponseMetadata +{ + public static AtomicOperationsResponseMetadata Instance { get; } = new(); + + private AtomicOperationsResponseMetadata() + { + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/EndpointResolver.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/EndpointResolver.cs new file mode 100644 index 0000000000..e4c074f081 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/EndpointResolver.cs @@ -0,0 +1,38 @@ +using System.Reflection; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; +using Microsoft.AspNetCore.Mvc.Routing; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata; + +internal sealed class EndpointResolver +{ + public static EndpointResolver Instance { get; } = new(); + + private EndpointResolver() + { + } + + public JsonApiEndpoints GetEndpoint(MethodInfo controllerAction) + { + ArgumentNullException.ThrowIfNull(controllerAction); + + if (!IsJsonApiController(controllerAction)) + { + return JsonApiEndpoints.None; + } + + IEnumerable httpMethodAttributes = controllerAction.GetCustomAttributes(true); + return httpMethodAttributes.GetJsonApiEndpoint(); + } + + private bool IsJsonApiController(MethodInfo controllerAction) + { + return typeof(CoreJsonApiController).IsAssignableFrom(controllerAction.ReflectedType); + } + + public bool IsAtomicOperationsController(MethodInfo controllerAction) + { + return typeof(BaseJsonApiOperationsController).IsAssignableFrom(controllerAction.ReflectedType); + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/IJsonApiEndpointMetadata.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/IJsonApiEndpointMetadata.cs new file mode 100644 index 0000000000..01a8247ec5 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/IJsonApiEndpointMetadata.cs @@ -0,0 +1,3 @@ +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata; + +internal interface IJsonApiEndpointMetadata; diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/IJsonApiRequestMetadata.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/IJsonApiRequestMetadata.cs new file mode 100644 index 0000000000..86fbddebb6 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/IJsonApiRequestMetadata.cs @@ -0,0 +1,3 @@ +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata; + +internal interface IJsonApiRequestMetadata : IJsonApiEndpointMetadata; diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/IJsonApiResponseMetadata.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/IJsonApiResponseMetadata.cs new file mode 100644 index 0000000000..85fb69e856 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/IJsonApiResponseMetadata.cs @@ -0,0 +1,3 @@ +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata; + +internal interface IJsonApiResponseMetadata : IJsonApiEndpointMetadata; diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/JsonApiEndpointMetadataContainer.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/JsonApiEndpointMetadataContainer.cs new file mode 100644 index 0000000000..60b7182eb6 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/JsonApiEndpointMetadataContainer.cs @@ -0,0 +1,10 @@ +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata; + +/// +/// Metadata available at runtime about a JsonApiDotNetCore endpoint. +/// +internal sealed class JsonApiEndpointMetadataContainer(IJsonApiRequestMetadata? requestMetadata, IJsonApiResponseMetadata? responseMetadata) +{ + public IJsonApiRequestMetadata? RequestMetadata { get; } = requestMetadata; + public IJsonApiResponseMetadata? ResponseMetadata { get; } = responseMetadata; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/JsonApiEndpointMetadataProvider.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/JsonApiEndpointMetadataProvider.cs new file mode 100644 index 0000000000..6fd6f9e42e --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/JsonApiEndpointMetadataProvider.cs @@ -0,0 +1,123 @@ +using System.Reflection; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; +using JsonApiDotNetCore.Resources.Annotations; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata; + +/// +/// Provides JsonApiDotNetCore related metadata for an ASP.NET controller action that can only be computed from the at +/// runtime. +/// +internal sealed class JsonApiEndpointMetadataProvider +{ + private readonly IControllerResourceMapping _controllerResourceMapping; + private readonly NonPrimaryDocumentTypeFactory _nonPrimaryDocumentTypeFactory; + + public JsonApiEndpointMetadataProvider(IControllerResourceMapping controllerResourceMapping, NonPrimaryDocumentTypeFactory nonPrimaryDocumentTypeFactory) + { + ArgumentNullException.ThrowIfNull(controllerResourceMapping); + ArgumentNullException.ThrowIfNull(nonPrimaryDocumentTypeFactory); + + _controllerResourceMapping = controllerResourceMapping; + _nonPrimaryDocumentTypeFactory = nonPrimaryDocumentTypeFactory; + } + + public JsonApiEndpointMetadataContainer Get(MethodInfo controllerAction) + { + ArgumentNullException.ThrowIfNull(controllerAction); + + if (EndpointResolver.Instance.IsAtomicOperationsController(controllerAction)) + { + return new JsonApiEndpointMetadataContainer(AtomicOperationsRequestMetadata.Instance, AtomicOperationsResponseMetadata.Instance); + } + + JsonApiEndpoints endpoint = EndpointResolver.Instance.GetEndpoint(controllerAction); + + if (endpoint == JsonApiEndpoints.None) + { + throw new NotSupportedException($"Unable to provide metadata for non-JSON:API endpoint '{controllerAction.ReflectedType!.FullName}'."); + } + + ResourceType? primaryResourceType = _controllerResourceMapping.GetResourceTypeForController(controllerAction.ReflectedType); + ConsistencyGuard.ThrowIf(primaryResourceType == null); + + IJsonApiRequestMetadata? requestMetadata = GetRequestMetadata(endpoint, primaryResourceType); + IJsonApiResponseMetadata? responseMetadata = GetResponseMetadata(endpoint, primaryResourceType); + return new JsonApiEndpointMetadataContainer(requestMetadata, responseMetadata); + } + + private IJsonApiRequestMetadata? GetRequestMetadata(JsonApiEndpoints endpoint, ResourceType primaryResourceType) + { + return endpoint switch + { + JsonApiEndpoints.Post => GetPostResourceRequestMetadata(primaryResourceType.ClrType), + JsonApiEndpoints.Patch => GetPatchResourceRequestMetadata(primaryResourceType.ClrType), + JsonApiEndpoints.PostRelationship or JsonApiEndpoints.PatchRelationship or JsonApiEndpoints.DeleteRelationship => GetRelationshipRequestMetadata( + primaryResourceType.Relationships, endpoint != JsonApiEndpoints.PatchRelationship), + _ => null + }; + } + + private static PrimaryRequestMetadata GetPostResourceRequestMetadata(Type resourceClrType) + { + Type documentType = typeof(CreateRequestDocument<>).MakeGenericType(resourceClrType); + + return new PrimaryRequestMetadata(documentType); + } + + private static PrimaryRequestMetadata GetPatchResourceRequestMetadata(Type resourceClrType) + { + Type documentType = typeof(UpdateRequestDocument<>).MakeGenericType(resourceClrType); + + return new PrimaryRequestMetadata(documentType); + } + + private RelationshipRequestMetadata GetRelationshipRequestMetadata(IEnumerable relationships, bool ignoreHasOneRelationships) + { + IEnumerable relationshipsOfEndpoint = ignoreHasOneRelationships ? relationships.OfType() : relationships; + + IDictionary requestDocumentTypesByRelationshipName = relationshipsOfEndpoint.ToDictionary(relationship => relationship.PublicName, + _nonPrimaryDocumentTypeFactory.GetForRelationshipRequest); + + return new RelationshipRequestMetadata(requestDocumentTypesByRelationshipName); + } + + private IJsonApiResponseMetadata? GetResponseMetadata(JsonApiEndpoints endpoint, ResourceType primaryResourceType) + { + return endpoint switch + { + JsonApiEndpoints.GetCollection or JsonApiEndpoints.GetSingle or JsonApiEndpoints.Post or JsonApiEndpoints.Patch => GetPrimaryResponseMetadata( + primaryResourceType.ClrType, endpoint == JsonApiEndpoints.GetCollection), + JsonApiEndpoints.GetSecondary => GetSecondaryResponseMetadata(primaryResourceType.Relationships), + JsonApiEndpoints.GetRelationship => GetRelationshipResponseMetadata(primaryResourceType.Relationships), + _ => null + }; + } + + private static PrimaryResponseMetadata GetPrimaryResponseMetadata(Type resourceClrType, bool endpointReturnsCollection) + { + Type documentOpenType = endpointReturnsCollection ? typeof(CollectionResponseDocument<>) : typeof(PrimaryResponseDocument<>); + Type documentType = documentOpenType.MakeGenericType(resourceClrType); + + return new PrimaryResponseMetadata(documentType); + } + + private SecondaryResponseMetadata GetSecondaryResponseMetadata(IEnumerable relationships) + { + IDictionary responseDocumentTypesByRelationshipName = relationships.ToDictionary(relationship => relationship.PublicName, + _nonPrimaryDocumentTypeFactory.GetForSecondaryResponse); + + return new SecondaryResponseMetadata(responseDocumentTypesByRelationshipName); + } + + private RelationshipResponseMetadata GetRelationshipResponseMetadata(IEnumerable relationships) + { + IDictionary responseDocumentTypesByRelationshipName = relationships.ToDictionary(relationship => relationship.PublicName, + _nonPrimaryDocumentTypeFactory.GetForRelationshipResponse); + + return new RelationshipResponseMetadata(responseDocumentTypesByRelationshipName); + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/NonPrimaryDocumentTypeFactory.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/NonPrimaryDocumentTypeFactory.cs new file mode 100644 index 0000000000..7550d59ab3 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/NonPrimaryDocumentTypeFactory.cs @@ -0,0 +1,80 @@ +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Relationships; +using JsonApiDotNetCore.Resources.Annotations; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata; + +internal sealed class NonPrimaryDocumentTypeFactory +{ + private static readonly DocumentOpenTypes SecondaryResponseDocumentOpenTypes = new(typeof(CollectionResponseDocument<>), + typeof(NullableSecondaryResponseDocument<>), typeof(SecondaryResponseDocument<>)); + + private static readonly DocumentOpenTypes RelationshipRequestDocumentOpenTypes = new(typeof(ToManyInRequest<>), + typeof(NullableToOneInRequest<>), typeof(ToOneInRequest<>)); + + private static readonly DocumentOpenTypes RelationshipResponseDocumentOpenTypes = new(typeof(IdentifierCollectionResponseDocument<>), + typeof(NullableIdentifierResponseDocument<>), typeof(IdentifierResponseDocument<>)); + + private readonly ResourceFieldValidationMetadataProvider _resourceFieldValidationMetadataProvider; + + public NonPrimaryDocumentTypeFactory(ResourceFieldValidationMetadataProvider resourceFieldValidationMetadataProvider) + { + ArgumentNullException.ThrowIfNull(resourceFieldValidationMetadataProvider); + + _resourceFieldValidationMetadataProvider = resourceFieldValidationMetadataProvider; + } + + public Type GetForSecondaryResponse(RelationshipAttribute relationship) + { + ArgumentNullException.ThrowIfNull(relationship); + + return Get(relationship, SecondaryResponseDocumentOpenTypes); + } + + public Type GetForRelationshipRequest(RelationshipAttribute relationship) + { + ArgumentNullException.ThrowIfNull(relationship); + + return Get(relationship, RelationshipRequestDocumentOpenTypes); + } + + public Type GetForRelationshipResponse(RelationshipAttribute relationship) + { + ArgumentNullException.ThrowIfNull(relationship); + + return Get(relationship, RelationshipResponseDocumentOpenTypes); + } + + private Type Get(RelationshipAttribute relationship, DocumentOpenTypes types) + { + // @formatter:nested_ternary_style expanded + + Type documentOpenType = relationship is HasManyAttribute + ? types.ManyDataOpenType + : _resourceFieldValidationMetadataProvider.IsNullable(relationship) + ? types.NullableSingleDataOpenType + : types.SingleDataOpenType; + + // @formatter:nested_ternary_style restore + + return documentOpenType.MakeGenericType(relationship.RightType.ClrType); + } + + private sealed class DocumentOpenTypes + { + public Type ManyDataOpenType { get; } + public Type NullableSingleDataOpenType { get; } + public Type SingleDataOpenType { get; } + + public DocumentOpenTypes(Type manyDataOpenType, Type nullableSingleDataOpenType, Type singleDataOpenType) + { + ArgumentNullException.ThrowIfNull(manyDataOpenType); + ArgumentNullException.ThrowIfNull(nullableSingleDataOpenType); + ArgumentNullException.ThrowIfNull(singleDataOpenType); + + ManyDataOpenType = manyDataOpenType; + NullableSingleDataOpenType = nullableSingleDataOpenType; + SingleDataOpenType = singleDataOpenType; + } + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/NonPrimaryEndpointMetadata.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/NonPrimaryEndpointMetadata.cs new file mode 100644 index 0000000000..ed43dc4da8 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/NonPrimaryEndpointMetadata.cs @@ -0,0 +1,13 @@ +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata; + +internal abstract class NonPrimaryEndpointMetadata +{ + public IDictionary DocumentTypesByRelationshipName { get; } + + protected NonPrimaryEndpointMetadata(IDictionary documentTypesByRelationshipName) + { + ArgumentNullException.ThrowIfNull(documentTypesByRelationshipName); + + DocumentTypesByRelationshipName = documentTypesByRelationshipName; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/PrimaryRequestMetadata.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/PrimaryRequestMetadata.cs new file mode 100644 index 0000000000..7c224417f1 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/PrimaryRequestMetadata.cs @@ -0,0 +1,13 @@ +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata; + +internal sealed class PrimaryRequestMetadata : IJsonApiRequestMetadata +{ + public Type DocumentType { get; } + + public PrimaryRequestMetadata(Type documentType) + { + ArgumentNullException.ThrowIfNull(documentType); + + DocumentType = documentType; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/PrimaryResponseMetadata.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/PrimaryResponseMetadata.cs new file mode 100644 index 0000000000..2d2590be7d --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/PrimaryResponseMetadata.cs @@ -0,0 +1,13 @@ +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata; + +internal sealed class PrimaryResponseMetadata : IJsonApiResponseMetadata +{ + public Type DocumentType { get; } + + public PrimaryResponseMetadata(Type documentType) + { + ArgumentNullException.ThrowIfNull(documentType); + + DocumentType = documentType; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/RelationshipRequestMetadata.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/RelationshipRequestMetadata.cs new file mode 100644 index 0000000000..e2636da079 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/RelationshipRequestMetadata.cs @@ -0,0 +1,4 @@ +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata; + +internal sealed class RelationshipRequestMetadata(IDictionary documentTypesByRelationshipName) + : NonPrimaryEndpointMetadata(documentTypesByRelationshipName), IJsonApiRequestMetadata; diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/RelationshipResponseMetadata.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/RelationshipResponseMetadata.cs new file mode 100644 index 0000000000..7221dfbe5e --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/RelationshipResponseMetadata.cs @@ -0,0 +1,4 @@ +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata; + +internal sealed class RelationshipResponseMetadata(IDictionary documentTypesByRelationshipName) + : NonPrimaryEndpointMetadata(documentTypesByRelationshipName), IJsonApiResponseMetadata; diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/RelationshipTypeFactory.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/RelationshipTypeFactory.cs new file mode 100644 index 0000000000..be5a6fd30c --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/RelationshipTypeFactory.cs @@ -0,0 +1,44 @@ +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Relationships; +using JsonApiDotNetCore.Resources.Annotations; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata; + +internal sealed class RelationshipTypeFactory +{ + private readonly NonPrimaryDocumentTypeFactory _nonPrimaryDocumentTypeFactory; + private readonly ResourceFieldValidationMetadataProvider _resourceFieldValidationMetadataProvider; + + public RelationshipTypeFactory(NonPrimaryDocumentTypeFactory nonPrimaryDocumentTypeFactory, + ResourceFieldValidationMetadataProvider resourceFieldValidationMetadataProvider) + { + ArgumentNullException.ThrowIfNull(nonPrimaryDocumentTypeFactory); + ArgumentNullException.ThrowIfNull(resourceFieldValidationMetadataProvider); + + _nonPrimaryDocumentTypeFactory = nonPrimaryDocumentTypeFactory; + _resourceFieldValidationMetadataProvider = resourceFieldValidationMetadataProvider; + } + + public Type GetForRequest(RelationshipAttribute relationship) + { + ArgumentNullException.ThrowIfNull(relationship); + + return _nonPrimaryDocumentTypeFactory.GetForRelationshipRequest(relationship); + } + + public Type GetForResponse(RelationshipAttribute relationship) + { + ArgumentNullException.ThrowIfNull(relationship); + + // @formatter:nested_ternary_style expanded + + Type relationshipDataOpenType = relationship is HasManyAttribute + ? typeof(ToManyInResponse<>) + : _resourceFieldValidationMetadataProvider.IsNullable(relationship) + ? typeof(NullableToOneInResponse<>) + : typeof(ToOneInResponse<>); + + // @formatter:nested_ternary_style restore + + return relationshipDataOpenType.MakeGenericType(relationship.RightType.ClrType); + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/SecondaryResponseMetadata.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/SecondaryResponseMetadata.cs new file mode 100644 index 0000000000..39b8ce8d4f --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiMetadata/SecondaryResponseMetadata.cs @@ -0,0 +1,4 @@ +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata; + +internal sealed class SecondaryResponseMetadata(IDictionary documentTypesByRelationshipName) + : NonPrimaryEndpointMetadata(documentTypesByRelationshipName), IJsonApiResponseMetadata; diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/AddToRelationshipOperation.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/AddToRelationshipOperation.cs new file mode 100644 index 0000000000..bf461fe41a --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/AddToRelationshipOperation.cs @@ -0,0 +1,24 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.AtomicOperations; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class AddToRelationshipOperation : AtomicOperation + where TResource : IIdentifiable +{ + [Required] + [JsonPropertyName("op")] + public string Op { get; set; } = null!; + + [Required] + [JsonPropertyName("ref")] + public object Ref { get; set; } = null!; + + [Required] + [JsonPropertyName("data")] + public ICollection> Data { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/AtomicOperation.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/AtomicOperation.cs new file mode 100644 index 0000000000..6f0934008d --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/AtomicOperation.cs @@ -0,0 +1,11 @@ +using System.Text.Json.Serialization; +using JetBrains.Annotations; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.AtomicOperations; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal abstract class AtomicOperation : IHasMeta +{ + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/AtomicResult.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/AtomicResult.cs new file mode 100644 index 0000000000..f4dec21cbf --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/AtomicResult.cs @@ -0,0 +1,15 @@ +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.AtomicOperations; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class AtomicResult : IHasMeta +{ + [JsonPropertyName("data")] + public ResourceInResponse Data { get; set; } = null!; + + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/CreateOperation.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/CreateOperation.cs new file mode 100644 index 0000000000..266712e666 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/CreateOperation.cs @@ -0,0 +1,20 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.AtomicOperations; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class CreateOperation : AtomicOperation + where TResource : IIdentifiable +{ + [Required] + [JsonPropertyName("op")] + public string Op { get; set; } = null!; + + [Required] + [JsonPropertyName("data")] + public DataInCreateRequest Data { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/DeleteOperation.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/DeleteOperation.cs new file mode 100644 index 0000000000..838b4400dd --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/DeleteOperation.cs @@ -0,0 +1,20 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.AtomicOperations; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class DeleteOperation : AtomicOperation + where TResource : IIdentifiable +{ + [Required] + [JsonPropertyName("op")] + public string Op { get; set; } = null!; + + [Required] + [JsonPropertyName("ref")] + public IdentifierInRequest Ref { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/RemoveFromRelationshipOperation.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/RemoveFromRelationshipOperation.cs new file mode 100644 index 0000000000..eafe36028e --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/RemoveFromRelationshipOperation.cs @@ -0,0 +1,24 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.AtomicOperations; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class RemoveFromRelationshipOperation : AtomicOperation + where TResource : IIdentifiable +{ + [Required] + [JsonPropertyName("op")] + public string Op { get; set; } = null!; + + [Required] + [JsonPropertyName("ref")] + public object Ref { get; set; } = null!; + + [Required] + [JsonPropertyName("data")] + public ICollection> Data { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/UpdateOperation.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/UpdateOperation.cs new file mode 100644 index 0000000000..cb576c3a4f --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/UpdateOperation.cs @@ -0,0 +1,23 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.AtomicOperations; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class UpdateOperation : AtomicOperation + where TResource : IIdentifiable +{ + [Required] + [JsonPropertyName("op")] + public string Op { get; set; } = null!; + + [JsonPropertyName("ref")] + public IdentifierInRequest Ref { get; set; } = null!; + + [Required] + [JsonPropertyName("data")] + public DataInUpdateRequest Data { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/UpdateToManyRelationshipOperation.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/UpdateToManyRelationshipOperation.cs new file mode 100644 index 0000000000..2725b3dd9f --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/UpdateToManyRelationshipOperation.cs @@ -0,0 +1,24 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.AtomicOperations; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class UpdateToManyRelationshipOperation : AtomicOperation + where TResource : IIdentifiable +{ + [Required] + [JsonPropertyName("op")] + public string Op { get; set; } = null!; + + [Required] + [JsonPropertyName("ref")] + public object Ref { get; set; } = null!; + + [Required] + [JsonPropertyName("data")] + public ICollection> Data { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/UpdateToOneRelationshipOperation.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/UpdateToOneRelationshipOperation.cs new file mode 100644 index 0000000000..71c6528605 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/AtomicOperations/UpdateToOneRelationshipOperation.cs @@ -0,0 +1,25 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.AtomicOperations; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class UpdateToOneRelationshipOperation : AtomicOperation + where TResource : IIdentifiable +{ + [Required] + [JsonPropertyName("op")] + public string Op { get; set; } = null!; + + [Required] + [JsonPropertyName("ref")] + public object Ref { get; set; } = null!; + + [Required] + [JsonPropertyName("data")] + // Nullability of this property is determined based on the nullability of the to-one relationship. + public IdentifierInRequest? Data { get; set; } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/CollectionResponseDocument.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/CollectionResponseDocument.cs new file mode 100644 index 0000000000..bfb0131f07 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/CollectionResponseDocument.cs @@ -0,0 +1,30 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Links; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class CollectionResponseDocument : IHasMeta + where TResource : IIdentifiable +{ + [JsonPropertyName("jsonapi")] + public Jsonapi Jsonapi { get; set; } = null!; + + [Required] + [JsonPropertyName("links")] + public ResourceCollectionTopLevelLinks Links { get; set; } = null!; + + [Required] + [JsonPropertyName("data")] + public ICollection> Data { get; set; } = null!; + + [JsonPropertyName("included")] + public IList Included { get; set; } = null!; + + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/CreateRequestDocument.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/CreateRequestDocument.cs new file mode 100644 index 0000000000..388d659398 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/CreateRequestDocument.cs @@ -0,0 +1,19 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class CreateRequestDocument : IHasMeta + where TResource : IIdentifiable +{ + [Required] + [JsonPropertyName("data")] + public DataInCreateRequest Data { get; set; } = null!; + + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/ErrorResponseDocument.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/ErrorResponseDocument.cs new file mode 100644 index 0000000000..750c83ef74 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/ErrorResponseDocument.cs @@ -0,0 +1,25 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Links; +using JsonApiDotNetCore.Serialization.Objects; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class ErrorResponseDocument : IHasMeta +{ + [JsonPropertyName("jsonapi")] + public Jsonapi Jsonapi { get; set; } = null!; + + [Required] + [JsonPropertyName("links")] + public ErrorTopLevelLinks Links { get; set; } = null!; + + [Required] + [JsonPropertyName("errors")] + public IList Errors { get; set; } = new List(); + + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/IdentifierCollectionResponseDocument.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/IdentifierCollectionResponseDocument.cs new file mode 100644 index 0000000000..bf50821888 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/IdentifierCollectionResponseDocument.cs @@ -0,0 +1,27 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Links; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class IdentifierCollectionResponseDocument : IHasMeta + where TResource : IIdentifiable +{ + [JsonPropertyName("jsonapi")] + public Jsonapi Jsonapi { get; set; } = null!; + + [Required] + [JsonPropertyName("links")] + public ResourceIdentifierCollectionTopLevelLinks Links { get; set; } = null!; + + [Required] + [JsonPropertyName("data")] + public ICollection> Data { get; set; } = null!; + + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/IdentifierResponseDocument.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/IdentifierResponseDocument.cs new file mode 100644 index 0000000000..3c44955edc --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/IdentifierResponseDocument.cs @@ -0,0 +1,27 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Links; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class IdentifierResponseDocument : IHasMeta + where TResource : IIdentifiable +{ + [JsonPropertyName("jsonapi")] + public Jsonapi Jsonapi { get; set; } = null!; + + [Required] + [JsonPropertyName("links")] + public ResourceIdentifierTopLevelLinks Links { get; set; } = null!; + + [Required] + [JsonPropertyName("data")] + public IdentifierInResponse Data { get; set; } = null!; + + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/NullableIdentifierResponseDocument.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/NullableIdentifierResponseDocument.cs new file mode 100644 index 0000000000..1386bec001 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/NullableIdentifierResponseDocument.cs @@ -0,0 +1,29 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Links; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; + +// Types in the JsonApiObjects namespace are never touched by ASP.NET ModelState validation, therefore using a non-nullable reference type for a property does not +// imply this property is required. Instead, we use [Required] explicitly, because this is how Swashbuckle is instructed to mark properties as required. +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class NullableIdentifierResponseDocument : IHasMeta + where TResource : IIdentifiable +{ + [JsonPropertyName("jsonapi")] + public Jsonapi Jsonapi { get; set; } = null!; + + [Required] + [JsonPropertyName("links")] + public ResourceIdentifierTopLevelLinks Links { get; set; } = null!; + + [Required] + [JsonPropertyName("data")] + public IdentifierInResponse? Data { get; set; } + + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/NullableSecondaryResponseDocument.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/NullableSecondaryResponseDocument.cs new file mode 100644 index 0000000000..6d6d240a5b --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/NullableSecondaryResponseDocument.cs @@ -0,0 +1,30 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Links; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class NullableSecondaryResponseDocument : IHasMeta + where TResource : IIdentifiable +{ + [JsonPropertyName("jsonapi")] + public Jsonapi Jsonapi { get; set; } = null!; + + [Required] + [JsonPropertyName("links")] + public ResourceTopLevelLinks Links { get; set; } = null!; + + [Required] + [JsonPropertyName("data")] + public DataInResponse? Data { get; set; } + + [JsonPropertyName("included")] + public IList Included { get; set; } = null!; + + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/OperationsRequestDocument.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/OperationsRequestDocument.cs new file mode 100644 index 0000000000..6bd3a1dad2 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/OperationsRequestDocument.cs @@ -0,0 +1,18 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.AtomicOperations; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class OperationsRequestDocument : IHasMeta +{ + [Required] + [MinLength(1)] + [JsonPropertyName("atomic:operations")] + public ICollection Operations { get; set; } = null!; + + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/OperationsResponseDocument.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/OperationsResponseDocument.cs new file mode 100644 index 0000000000..1c962fba84 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/OperationsResponseDocument.cs @@ -0,0 +1,26 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.AtomicOperations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Links; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class OperationsResponseDocument : IHasMeta +{ + [JsonPropertyName("jsonapi")] + public Jsonapi Jsonapi { get; set; } = null!; + + [Required] + [JsonPropertyName("links")] + public ResourceTopLevelLinks Links { get; set; } = null!; + + [Required] + [MinLength(1)] + [JsonPropertyName("atomic:results")] + public IList Results { get; set; } = null!; + + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/PrimaryResponseDocument.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/PrimaryResponseDocument.cs new file mode 100644 index 0000000000..1956fb8758 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/PrimaryResponseDocument.cs @@ -0,0 +1,30 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Links; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class PrimaryResponseDocument : IHasMeta + where TResource : IIdentifiable +{ + [JsonPropertyName("jsonapi")] + public Jsonapi Jsonapi { get; set; } = null!; + + [Required] + [JsonPropertyName("links")] + public ResourceTopLevelLinks Links { get; set; } = null!; + + [Required] + [JsonPropertyName("data")] + public DataInResponse Data { get; set; } = null!; + + [JsonPropertyName("included")] + public IList Included { get; set; } = null!; + + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/SecondaryResponseDocument.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/SecondaryResponseDocument.cs new file mode 100644 index 0000000000..6a90db36e1 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/SecondaryResponseDocument.cs @@ -0,0 +1,30 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Links; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class SecondaryResponseDocument : IHasMeta + where TResource : IIdentifiable +{ + [JsonPropertyName("jsonapi")] + public Jsonapi Jsonapi { get; set; } = null!; + + [Required] + [JsonPropertyName("links")] + public ResourceTopLevelLinks Links { get; set; } = null!; + + [Required] + [JsonPropertyName("data")] + public DataInResponse Data { get; set; } = null!; + + [JsonPropertyName("included")] + public IList Included { get; set; } = null!; + + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/UpdateRequestDocument.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/UpdateRequestDocument.cs new file mode 100644 index 0000000000..cbeec3e86b --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Documents/UpdateRequestDocument.cs @@ -0,0 +1,19 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class UpdateRequestDocument : IHasMeta + where TResource : IIdentifiable +{ + [Required] + [JsonPropertyName("data")] + public DataInUpdateRequest Data { get; set; } = null!; + + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/IHasMeta.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/IHasMeta.cs new file mode 100644 index 0000000000..64315dee42 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/IHasMeta.cs @@ -0,0 +1,9 @@ +using JetBrains.Annotations; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal interface IHasMeta +{ + Meta Meta { get; set; } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Jsonapi.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Jsonapi.cs new file mode 100644 index 0000000000..692b5d77ac --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Jsonapi.cs @@ -0,0 +1,20 @@ +using System.Text.Json.Serialization; +using JetBrains.Annotations; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class Jsonapi : IHasMeta +{ + [JsonPropertyName("version")] + public string Version { get; set; } = null!; + + [JsonPropertyName("ext")] + public ICollection Ext { get; set; } = null!; + + [JsonPropertyName("profile")] + public ICollection Profile { get; set; } = null!; + + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Links/ErrorTopLevelLinks.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Links/ErrorTopLevelLinks.cs new file mode 100644 index 0000000000..f98c9eb480 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Links/ErrorTopLevelLinks.cs @@ -0,0 +1,14 @@ +using System.Text.Json.Serialization; +using JetBrains.Annotations; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Links; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class ErrorTopLevelLinks +{ + [JsonPropertyName("self")] + public string Self { get; set; } = null!; + + [JsonPropertyName("describedby")] + public string Describedby { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Links/RelationshipLinks.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Links/RelationshipLinks.cs new file mode 100644 index 0000000000..0bdae58dee --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Links/RelationshipLinks.cs @@ -0,0 +1,14 @@ +using System.Text.Json.Serialization; +using JetBrains.Annotations; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Links; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class RelationshipLinks +{ + [JsonPropertyName("self")] + public string Self { get; set; } = null!; + + [JsonPropertyName("related")] + public string Related { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Links/ResourceCollectionTopLevelLinks.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Links/ResourceCollectionTopLevelLinks.cs new file mode 100644 index 0000000000..65710af45f --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Links/ResourceCollectionTopLevelLinks.cs @@ -0,0 +1,26 @@ +using System.Text.Json.Serialization; +using JetBrains.Annotations; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Links; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class ResourceCollectionTopLevelLinks +{ + [JsonPropertyName("self")] + public string Self { get; set; } = null!; + + [JsonPropertyName("describedby")] + public string Describedby { get; set; } = null!; + + [JsonPropertyName("first")] + public string First { get; set; } = null!; + + [JsonPropertyName("last")] + public string Last { get; set; } = null!; + + [JsonPropertyName("prev")] + public string Prev { get; set; } = null!; + + [JsonPropertyName("next")] + public string Next { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Links/ResourceIdentifierCollectionTopLevelLinks.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Links/ResourceIdentifierCollectionTopLevelLinks.cs new file mode 100644 index 0000000000..8b9a3aaf55 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Links/ResourceIdentifierCollectionTopLevelLinks.cs @@ -0,0 +1,29 @@ +using System.Text.Json.Serialization; +using JetBrains.Annotations; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Links; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class ResourceIdentifierCollectionTopLevelLinks +{ + [JsonPropertyName("self")] + public string Self { get; set; } = null!; + + [JsonPropertyName("related")] + public string Related { get; set; } = null!; + + [JsonPropertyName("describedby")] + public string Describedby { get; set; } = null!; + + [JsonPropertyName("first")] + public string First { get; set; } = null!; + + [JsonPropertyName("last")] + public string Last { get; set; } = null!; + + [JsonPropertyName("prev")] + public string Prev { get; set; } = null!; + + [JsonPropertyName("next")] + public string Next { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Links/ResourceIdentifierTopLevelLinks.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Links/ResourceIdentifierTopLevelLinks.cs new file mode 100644 index 0000000000..9af21cf6a1 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Links/ResourceIdentifierTopLevelLinks.cs @@ -0,0 +1,17 @@ +using System.Text.Json.Serialization; +using JetBrains.Annotations; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Links; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class ResourceIdentifierTopLevelLinks +{ + [JsonPropertyName("self")] + public string Self { get; set; } = null!; + + [JsonPropertyName("related")] + public string Related { get; set; } = null!; + + [JsonPropertyName("describedby")] + public string Describedby { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Links/ResourceLinks.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Links/ResourceLinks.cs new file mode 100644 index 0000000000..a37ef69523 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Links/ResourceLinks.cs @@ -0,0 +1,11 @@ +using System.Text.Json.Serialization; +using JetBrains.Annotations; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Links; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class ResourceLinks +{ + [JsonPropertyName("self")] + public string Self { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Links/ResourceTopLevelLinks.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Links/ResourceTopLevelLinks.cs new file mode 100644 index 0000000000..531c8d10ad --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Links/ResourceTopLevelLinks.cs @@ -0,0 +1,14 @@ +using System.Text.Json.Serialization; +using JetBrains.Annotations; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Links; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class ResourceTopLevelLinks +{ + [JsonPropertyName("self")] + public string Self { get; set; } = null!; + + [JsonPropertyName("describedby")] + public string Describedby { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Meta.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Meta.cs new file mode 100644 index 0000000000..a85cd3498a --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Meta.cs @@ -0,0 +1,9 @@ +using JetBrains.Annotations; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class Meta +{ + // No members, because the component schema is custom-generated. +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/NullableToOneInRequest.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/NullableToOneInRequest.cs new file mode 100644 index 0000000000..13f3290102 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/NullableToOneInRequest.cs @@ -0,0 +1,19 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Relationships; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class NullableToOneInRequest : IHasMeta + where TResource : IIdentifiable +{ + [Required] + [JsonPropertyName("data")] + public IdentifierInRequest? Data { get; set; } + + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/NullableToOneInResponse.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/NullableToOneInResponse.cs new file mode 100644 index 0000000000..29d13dd1c2 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/NullableToOneInResponse.cs @@ -0,0 +1,23 @@ +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Links; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Relationships; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class NullableToOneInResponse : IHasMeta + where TResource : IIdentifiable +{ + // Non-required because the related controller may be unavailable when used in an include. + [JsonPropertyName("links")] + public RelationshipLinks Links { get; set; } = null!; + + // Non-required because related data may not be included in the response. + [JsonPropertyName("data")] + public IdentifierInResponse? Data { get; set; } + + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/ToManyInRequest.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/ToManyInRequest.cs new file mode 100644 index 0000000000..b80ab3a004 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/ToManyInRequest.cs @@ -0,0 +1,19 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Relationships; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class ToManyInRequest : IHasMeta + where TResource : IIdentifiable +{ + [Required] + [JsonPropertyName("data")] + public ICollection> Data { get; set; } = null!; + + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/ToManyInResponse.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/ToManyInResponse.cs new file mode 100644 index 0000000000..e60ab7f451 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/ToManyInResponse.cs @@ -0,0 +1,23 @@ +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Links; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Relationships; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class ToManyInResponse : IHasMeta + where TResource : IIdentifiable +{ + // Non-required because the related controller may be unavailable when used in an include. + [JsonPropertyName("links")] + public RelationshipLinks Links { get; set; } = null!; + + // Non-required because related data may not be included in the response. + [JsonPropertyName("data")] + public ICollection> Data { get; set; } = null!; + + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/ToOneInRequest.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/ToOneInRequest.cs new file mode 100644 index 0000000000..6404e84545 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/ToOneInRequest.cs @@ -0,0 +1,19 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Relationships; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class ToOneInRequest : IHasMeta + where TResource : IIdentifiable +{ + [Required] + [JsonPropertyName("data")] + public IdentifierInRequest Data { get; set; } = null!; + + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/ToOneInResponse.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/ToOneInResponse.cs new file mode 100644 index 0000000000..859a1de929 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/ToOneInResponse.cs @@ -0,0 +1,23 @@ +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Links; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Relationships; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class ToOneInResponse : IHasMeta + where TResource : IIdentifiable +{ + // Non-required because the related controller may be unavailable when used in an include. + [JsonPropertyName("links")] + public RelationshipLinks Links { get; set; } = null!; + + // Non-required because related data may not be included in the response. + [JsonPropertyName("data")] + public IdentifierInResponse Data { get; set; } = null!; + + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/AttributesInCreateRequest.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/AttributesInCreateRequest.cs new file mode 100644 index 0000000000..0b8fddc0da --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/AttributesInCreateRequest.cs @@ -0,0 +1,9 @@ +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; + +internal abstract class AttributesInCreateRequest; + +// ReSharper disable once UnusedTypeParameter +internal sealed class AttributesInCreateRequest : AttributesInCreateRequest + where TResource : IIdentifiable; diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/AttributesInResponse.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/AttributesInResponse.cs new file mode 100644 index 0000000000..d4b1bb728c --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/AttributesInResponse.cs @@ -0,0 +1,9 @@ +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; + +internal abstract class AttributesInResponse; + +// ReSharper disable once UnusedTypeParameter +internal sealed class AttributesInResponse : AttributesInResponse + where TResource : IIdentifiable; diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/AttributesInUpdateRequest.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/AttributesInUpdateRequest.cs new file mode 100644 index 0000000000..d41bf18782 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/AttributesInUpdateRequest.cs @@ -0,0 +1,9 @@ +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; + +internal abstract class AttributesInUpdateRequest; + +// ReSharper disable once UnusedTypeParameter +internal sealed class AttributesInUpdateRequest : AttributesInUpdateRequest + where TResource : IIdentifiable; diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/DataInCreateRequest.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/DataInCreateRequest.cs new file mode 100644 index 0000000000..ac416a1614 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/DataInCreateRequest.cs @@ -0,0 +1,25 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class DataInCreateRequest : ResourceInCreateRequest + where TResource : IIdentifiable +{ + [MinLength(1)] + [JsonPropertyName("id")] + public override string Id { get; set; } = null!; + + [MinLength(1)] + [JsonPropertyName("lid")] + public string Lid { get; set; } = null!; + + [JsonPropertyName("attributes")] + public AttributesInCreateRequest Attributes { get; set; } = null!; + + [JsonPropertyName("relationships")] + public RelationshipsInCreateRequest Relationships { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/DataInResponse.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/DataInResponse.cs new file mode 100644 index 0000000000..6015a3511d --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/DataInResponse.cs @@ -0,0 +1,26 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Links; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class DataInResponse : ResourceInResponse + where TResource : IIdentifiable +{ + [Required] + [JsonPropertyName("id")] + public override string Id { get; set; } = null!; + + [JsonPropertyName("attributes")] + public AttributesInResponse Attributes { get; set; } = null!; + + [JsonPropertyName("relationships")] + public RelationshipsInResponse Relationships { get; set; } = null!; + + // Non-required because the related controller may be unavailable when used in an include. + [JsonPropertyName("links")] + public ResourceLinks Links { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/DataInUpdateRequest.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/DataInUpdateRequest.cs new file mode 100644 index 0000000000..25167a5437 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/DataInUpdateRequest.cs @@ -0,0 +1,25 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class DataInUpdateRequest : ResourceInUpdateRequest + where TResource : IIdentifiable +{ + [MinLength(1)] + [JsonPropertyName("id")] + public override string Id { get; set; } = null!; + + [MinLength(1)] + [JsonPropertyName("lid")] + public string Lid { get; set; } = null!; + + [JsonPropertyName("attributes")] + public AttributesInUpdateRequest Attributes { get; set; } = null!; + + [JsonPropertyName("relationships")] + public RelationshipsInUpdateRequest Relationships { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/IResourceIdentity.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/IResourceIdentity.cs new file mode 100644 index 0000000000..52985d68d9 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/IResourceIdentity.cs @@ -0,0 +1,10 @@ +using JetBrains.Annotations; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal interface IResourceIdentity : IHasMeta +{ + string Type { get; set; } + string Id { get; set; } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/IdentifierInRequest.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/IdentifierInRequest.cs new file mode 100644 index 0000000000..f317498810 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/IdentifierInRequest.cs @@ -0,0 +1,30 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; + +internal class IdentifierInRequest : IHasMeta +{ + [Required] + [JsonPropertyName("type")] + public string Type { get; set; } = null!; + + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} + +// ReSharper disable once UnusedTypeParameter +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal class IdentifierInRequest : IdentifierInRequest, IResourceIdentity + where TResource : IIdentifiable +{ + [MinLength(1)] + [JsonPropertyName("id")] + public string Id { get; set; } = null!; + + [MinLength(1)] + [JsonPropertyName("lid")] + public string Lid { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/IdentifierInResponse.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/IdentifierInResponse.cs new file mode 100644 index 0000000000..47bf94ce17 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/IdentifierInResponse.cs @@ -0,0 +1,23 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; + +// ReSharper disable once UnusedTypeParameter +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class IdentifierInResponse : IResourceIdentity + where TResource : IIdentifiable +{ + [Required] + [JsonPropertyName("type")] + public string Type { get; set; } = null!; + + [Required] + [JsonPropertyName("id")] + public string Id { get; set; } = null!; + + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/RelationshipIdentifier.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/RelationshipIdentifier.cs new file mode 100644 index 0000000000..34afbf1dc2 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/RelationshipIdentifier.cs @@ -0,0 +1,17 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal sealed class RelationshipIdentifier : IdentifierInRequest + where TResource : IIdentifiable +{ + [Required] + [JsonPropertyName("relationship")] + public string Relationship { get; set; } = null!; + + // Meta is erased at runtime. +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/RelationshipsInCreateRequest.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/RelationshipsInCreateRequest.cs new file mode 100644 index 0000000000..44698c3b57 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/RelationshipsInCreateRequest.cs @@ -0,0 +1,9 @@ +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; + +internal abstract class RelationshipsInCreateRequest; + +// ReSharper disable once UnusedTypeParameter +internal sealed class RelationshipsInCreateRequest : RelationshipsInCreateRequest + where TResource : IIdentifiable; diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/RelationshipsInResponse.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/RelationshipsInResponse.cs new file mode 100644 index 0000000000..24222743ce --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/RelationshipsInResponse.cs @@ -0,0 +1,9 @@ +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; + +internal abstract class RelationshipsInResponse; + +// ReSharper disable once UnusedTypeParameter +internal sealed class RelationshipsInResponse : RelationshipsInResponse + where TResource : IIdentifiable; diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/RelationshipsInUpdateRequest.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/RelationshipsInUpdateRequest.cs new file mode 100644 index 0000000000..bc851b97d5 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/RelationshipsInUpdateRequest.cs @@ -0,0 +1,9 @@ +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; + +internal abstract class RelationshipsInUpdateRequest; + +// ReSharper disable once UnusedTypeParameter +internal sealed class RelationshipsInUpdateRequest : RelationshipsInUpdateRequest + where TResource : IIdentifiable; diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/ResourceData.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/ResourceData.cs new file mode 100644 index 0000000000..746c696545 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/ResourceData.cs @@ -0,0 +1,18 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using JetBrains.Annotations; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +internal abstract class ResourceData : IResourceIdentity +{ + [Required] + [JsonPropertyName("type")] + public string Type { get; set; } = null!; + + public abstract string Id { get; set; } + + [JsonPropertyName("meta")] + public Meta Meta { get; set; } = null!; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/ResourceInCreateRequest.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/ResourceInCreateRequest.cs new file mode 100644 index 0000000000..838ab6a4ca --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/ResourceInCreateRequest.cs @@ -0,0 +1,3 @@ +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; + +internal abstract class ResourceInCreateRequest : ResourceData; diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/ResourceInResponse.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/ResourceInResponse.cs new file mode 100644 index 0000000000..2df01cc319 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/ResourceInResponse.cs @@ -0,0 +1,3 @@ +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; + +internal abstract class ResourceInResponse : ResourceData; diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/ResourceInUpdateRequest.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/ResourceInUpdateRequest.cs new file mode 100644 index 0000000000..63e5faae72 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/ResourceObjects/ResourceInUpdateRequest.cs @@ -0,0 +1,3 @@ +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; + +internal abstract class ResourceInUpdateRequest : ResourceData; diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiPropertyName.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiPropertyName.cs new file mode 100644 index 0000000000..1526450f16 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiPropertyName.cs @@ -0,0 +1,19 @@ +#pragma warning disable AV1008 // Class should not be static + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +internal static class JsonApiPropertyName +{ + public const string Jsonapi = "jsonapi"; + public const string Links = "links"; + public const string Data = "data"; + public const string Type = "type"; + public const string Id = "id"; + public const string Lid = "lid"; + public const string Attributes = "attributes"; + public const string Relationships = "relationships"; + public const string Op = "op"; + public const string Ref = "ref"; + public const string Relationship = "relationship"; + public const string Meta = "meta"; +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiRequestAccessor.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiRequestAccessor.cs new file mode 100644 index 0000000000..b466d78442 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiRequestAccessor.cs @@ -0,0 +1,21 @@ +using JsonApiDotNetCore.Middleware; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +/// +internal sealed class JsonApiRequestAccessor : IJsonApiRequestAccessor +{ + private readonly IHttpContextAccessor _httpContextAccessor; + + /// + public IJsonApiRequest? Current => _httpContextAccessor.HttpContext?.RequestServices.GetService(); + + public JsonApiRequestAccessor(IHttpContextAccessor httpContextAccessor) + { + ArgumentNullException.ThrowIfNull(httpContextAccessor); + + _httpContextAccessor = httpContextAccessor; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiRequestFormatMetadataProvider.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiRequestFormatMetadataProvider.cs new file mode 100644 index 0000000000..6def822bd9 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiRequestFormatMetadataProvider.cs @@ -0,0 +1,42 @@ +using System.Diagnostics; +using JsonApiDotNetCore.Middleware; +using Microsoft.AspNetCore.Mvc.ApiExplorer; +using Microsoft.AspNetCore.Mvc.Formatters; +using Microsoft.Net.Http.Headers; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +internal sealed class JsonApiRequestFormatMetadataProvider : IInputFormatter, IApiRequestFormatMetadataProvider +{ + private static readonly string DefaultMediaType = JsonApiMediaType.Default.ToString(); + + /// + public bool CanRead(InputFormatterContext context) + { + return false; + } + + /// + public Task ReadAsync(InputFormatterContext context) + { + throw new UnreachableException(); + } + + /// + public IReadOnlyList GetSupportedContentTypes(string contentType, Type objectType) + { + ArgumentException.ThrowIfNullOrEmpty(contentType); + ArgumentNullException.ThrowIfNull(objectType); + + if (JsonApiSchemaFacts.IsRequestBodySchemaType(objectType) && MediaTypeHeaderValue.TryParse(contentType, out MediaTypeHeaderValue? headerValue) && + headerValue.MediaType.Equals(DefaultMediaType, StringComparison.OrdinalIgnoreCase)) + { + return new MediaTypeCollection + { + headerValue + }; + } + + return []; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiSchemaFacts.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiSchemaFacts.cs new file mode 100644 index 0000000000..bf91aed0e7 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiSchemaFacts.cs @@ -0,0 +1,54 @@ +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Relationships; + +#pragma warning disable AV1008 // Class should not be static + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +internal static class JsonApiSchemaFacts +{ + private static readonly Type[] RequestBodySchemaTypes = + [ + typeof(CreateRequestDocument<>), + typeof(UpdateRequestDocument<>), + typeof(ToOneInRequest<>), + typeof(NullableToOneInRequest<>), + typeof(ToManyInRequest<>), + typeof(OperationsRequestDocument) + ]; + + private static readonly Type[] SchemaTypesHavingNullableDataProperty = + [ + typeof(NullableToOneInRequest<>), + typeof(NullableToOneInResponse<>), + typeof(NullableSecondaryResponseDocument<>), + typeof(NullableIdentifierResponseDocument<>) + ]; + + private static readonly Type[] RelationshipInResponseSchemaTypes = + [ + typeof(ToOneInResponse<>), + typeof(ToManyInResponse<>), + typeof(NullableToOneInResponse<>) + ]; + + public static bool IsRequestBodySchemaType(Type schemaType) + { + Type lookupType = schemaType.ConstructedToOpenType(); + return RequestBodySchemaTypes.Contains(lookupType); + } + + public static bool HasNullableDataProperty(Type schemaType) + { + // Swashbuckle infers non-nullable because our Data properties are [Required]. + + Type lookupType = schemaType.ConstructedToOpenType(); + return SchemaTypesHavingNullableDataProperty.Contains(lookupType); + } + + public static bool IsRelationshipInResponseType(Type schemaType) + { + Type lookupType = schemaType.ConstructedToOpenType(); + return RelationshipInResponseSchemaTypes.Contains(lookupType); + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiSchemaIdSelector.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiSchemaIdSelector.cs new file mode 100644 index 0000000000..0e2fc803de --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiSchemaIdSelector.cs @@ -0,0 +1,208 @@ +using System.Text.Json; +using Humanizer; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.AtomicOperations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Relationships; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources.Annotations; +using JsonApiDotNetCore.Serialization.Objects; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +internal sealed class JsonApiSchemaIdSelector +{ + private const string ResourceTypeSchemaIdTemplate = "[ResourceName] Resource Type"; + private const string MetaSchemaIdTemplate = "Meta"; + + private const string ResourceAtomicOperationDiscriminatorValueTemplate = "[OperationCode] [ResourceName]"; + private const string UpdateRelationshipAtomicOperationDiscriminatorValueTemplate = "Update [ResourceName] [RelationshipName]"; + private const string AddToRelationshipAtomicOperationDiscriminatorValueTemplate = "Add To [ResourceName] [RelationshipName]"; + private const string RemoveFromRelationshipAtomicOperationDiscriminatorValueTemplate = "Remove From [ResourceName] [RelationshipName]"; + + private const string UpdateRelationshipAtomicOperationSchemaIdTemplate = "Update [ResourceName] [RelationshipName] Relationship Operation"; + private const string AddToRelationshipAtomicOperationSchemaIdTemplate = "Add To [ResourceName] [RelationshipName] Relationship Operation"; + private const string RemoveFromRelationshipAtomicOperationSchemaIdTemplate = "Remove From [ResourceName] [RelationshipName] Relationship Operation"; + private const string RelationshipIdentifierSchemaIdTemplate = "[ResourceName] [RelationshipName] Relationship Identifier"; + private const string RelationshipNameSchemaIdTemplate = "[ResourceName] [RelationshipName] Relationship Name"; + + private static readonly Dictionary SchemaTypeToTemplateMap = new() + { + [typeof(CreateRequestDocument<>)] = "Create [ResourceName] Request Document", + [typeof(UpdateRequestDocument<>)] = "Update [ResourceName] Request Document", + [typeof(ResourceInCreateRequest)] = "Resource In Create Request", + [typeof(DataInCreateRequest<>)] = "Data In Create [ResourceName] Request", + [typeof(AttributesInCreateRequest)] = "Attributes In Create Request", + [typeof(AttributesInCreateRequest<>)] = "Attributes In Create [ResourceName] Request", + [typeof(RelationshipsInCreateRequest)] = "Relationships In Create Request", + [typeof(RelationshipsInCreateRequest<>)] = "Relationships In Create [ResourceName] Request", + [typeof(ResourceInUpdateRequest)] = "Resource In Update Request", + [typeof(DataInUpdateRequest<>)] = "Data In Update [ResourceName] Request", + [typeof(AttributesInUpdateRequest)] = "Attributes In Update Request", + [typeof(AttributesInUpdateRequest<>)] = "Attributes In Update [ResourceName] Request", + [typeof(RelationshipsInUpdateRequest)] = "Relationships In Update Request", + [typeof(RelationshipsInUpdateRequest<>)] = "Relationships In Update [ResourceName] Request", + [typeof(ToOneInRequest<>)] = "To One [ResourceName] In Request", + [typeof(NullableToOneInRequest<>)] = "Nullable To One [ResourceName] In Request", + [typeof(ToManyInRequest<>)] = "To Many [ResourceName] In Request", + [typeof(PrimaryResponseDocument<>)] = "Primary [ResourceName] Response Document", + [typeof(SecondaryResponseDocument<>)] = "Secondary [ResourceName] Response Document", + [typeof(NullableSecondaryResponseDocument<>)] = "Nullable Secondary [ResourceName] Response Document", + [typeof(CollectionResponseDocument<>)] = "[ResourceName] Collection Response Document", + [typeof(IdentifierResponseDocument<>)] = "[ResourceName] Identifier Response Document", + [typeof(NullableIdentifierResponseDocument<>)] = "Nullable [ResourceName] Identifier Response Document", + [typeof(IdentifierCollectionResponseDocument<>)] = "[ResourceName] Identifier Collection Response Document", + [typeof(ToOneInResponse<>)] = "To One [ResourceName] In Response", + [typeof(NullableToOneInResponse<>)] = "Nullable To One [ResourceName] In Response", + [typeof(ToManyInResponse<>)] = "To Many [ResourceName] In Response", + [typeof(ResourceInResponse)] = "Resource In Response", + [typeof(DataInResponse<>)] = "Data In [ResourceName] Response", + [typeof(AttributesInResponse<>)] = "Attributes In [ResourceName] Response", + [typeof(RelationshipsInResponse<>)] = "Relationships In [ResourceName] Response", + [typeof(IdentifierInRequest)] = "Identifier In Request", + [typeof(IdentifierInRequest<>)] = "[ResourceName] Identifier In Request", + [typeof(IdentifierInResponse<>)] = "[ResourceName] Identifier In Response", + [typeof(CreateOperation<>)] = "Create [ResourceName] Operation", + [typeof(UpdateOperation<>)] = "Update [ResourceName] Operation", + [typeof(DeleteOperation<>)] = "Delete [ResourceName] Operation", + [typeof(UpdateToOneRelationshipOperation<>)] = "Temporary Update [ResourceName] To One Relationship Operation", + [typeof(UpdateToManyRelationshipOperation<>)] = "Temporary Update [ResourceName] To Many Relationship Operation", + [typeof(AddToRelationshipOperation<>)] = "Temporary Add To [ResourceName] Relationship Operation", + [typeof(RemoveFromRelationshipOperation<>)] = "Temporary Remove From [ResourceName] Relationship Operation" + }; + + private readonly IJsonApiOptions _options; + private readonly IResourceGraph _resourceGraph; + + public JsonApiSchemaIdSelector(IJsonApiOptions options, IResourceGraph resourceGraph) + { + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(resourceGraph); + + _options = options; + _resourceGraph = resourceGraph; + } + + public string GetSchemaId(Type type) + { + ArgumentNullException.ThrowIfNull(type); + + ResourceType? resourceType = _resourceGraph.FindResourceType(type); + + if (resourceType != null) + { + return resourceType.PublicName.Singularize(); + } + + Type openType = type.ConstructedToOpenType(); + + if (openType != type) + { + if (SchemaTypeToTemplateMap.TryGetValue(openType, out string? schemaTemplate)) + { + Type resourceClrType = type.GetGenericArguments().First(); + resourceType = _resourceGraph.GetResourceType(resourceClrType); + + return ApplySchemaTemplate(schemaTemplate, resourceType, null, null); + } + } + else + { + if (SchemaTypeToTemplateMap.TryGetValue(type, out string? schemaTemplate)) + { + return ApplySchemaTemplate(schemaTemplate, null, null, null); + } + } + + // Used for a fixed set of non-generic types, such as Jsonapi, ResourceCollectionTopLevelLinks etc. + return ApplySchemaTemplate(type.Name, null, null, null); + } + + private string ApplySchemaTemplate(string schemaTemplate, ResourceType? resourceType, string? relationshipName, AtomicOperationCode? operationCode) + { + string schemaId = schemaTemplate; + + schemaId = resourceType != null + ? schemaId.Replace("[ResourceName]", resourceType.PublicName.Singularize()).Pascalize() + : schemaId.Replace("[ResourceName]", "$$$").Pascalize().Replace("$$$", string.Empty); + + if (relationshipName != null) + { + schemaId = schemaId.Replace("[RelationshipName]", relationshipName.Pascalize()); + } + + if (operationCode != null) + { + schemaId = schemaId.Replace("[OperationCode]", operationCode.Value.ToString().Pascalize()); + } + + string pascalCaseSchemaId = schemaId.Pascalize(); + + JsonNamingPolicy? namingPolicy = _options.SerializerOptions.PropertyNamingPolicy; + return namingPolicy != null ? namingPolicy.ConvertName(pascalCaseSchemaId) : pascalCaseSchemaId; + } + + public string GetResourceTypeSchemaId(ResourceType? resourceType) + { + return ApplySchemaTemplate(ResourceTypeSchemaIdTemplate, resourceType, null, null); + } + + public string GetMetaSchemaId() + { + return ApplySchemaTemplate(MetaSchemaIdTemplate, null, null, null); + } + + public string GetAtomicOperationCodeSchemaId(AtomicOperationCode operationCode) + { + return ApplySchemaTemplate("[OperationCode] Operation Code", null, null, operationCode); + } + + public string GetAtomicOperationDiscriminatorValue(AtomicOperationCode operationCode, ResourceType resourceType) + { + ArgumentNullException.ThrowIfNull(resourceType); + + return ApplySchemaTemplate(ResourceAtomicOperationDiscriminatorValueTemplate, resourceType, null, operationCode); + } + + public string GetAtomicOperationDiscriminatorValue(AtomicOperationCode operationCode, RelationshipAttribute relationship) + { + ArgumentNullException.ThrowIfNull(relationship); + + string schemaIdTemplate = operationCode switch + { + AtomicOperationCode.Add => AddToRelationshipAtomicOperationDiscriminatorValueTemplate, + AtomicOperationCode.Remove => RemoveFromRelationshipAtomicOperationDiscriminatorValueTemplate, + _ => UpdateRelationshipAtomicOperationDiscriminatorValueTemplate + }; + + return ApplySchemaTemplate(schemaIdTemplate, relationship.LeftType, relationship.PublicName, null); + } + + public string GetRelationshipAtomicOperationSchemaId(RelationshipAttribute relationship, AtomicOperationCode operationCode) + { + ArgumentNullException.ThrowIfNull(relationship); + + string schemaIdTemplate = operationCode switch + { + AtomicOperationCode.Add => AddToRelationshipAtomicOperationSchemaIdTemplate, + AtomicOperationCode.Remove => RemoveFromRelationshipAtomicOperationSchemaIdTemplate, + _ => UpdateRelationshipAtomicOperationSchemaIdTemplate + }; + + return ApplySchemaTemplate(schemaIdTemplate, relationship.LeftType, relationship.PublicName, null); + } + + public string GetRelationshipIdentifierSchemaId(RelationshipAttribute relationship) + { + ArgumentNullException.ThrowIfNull(relationship); + + return ApplySchemaTemplate(RelationshipIdentifierSchemaIdTemplate, relationship.LeftType, relationship.PublicName, null); + } + + public string GetRelationshipNameSchemaId(RelationshipAttribute relationship) + { + ArgumentNullException.ThrowIfNull(relationship); + + return ApplySchemaTemplate(RelationshipNameSchemaIdTemplate, relationship.LeftType, relationship.PublicName, null); + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ObjectExtensions.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ObjectExtensions.cs new file mode 100644 index 0000000000..accd03d7c4 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ObjectExtensions.cs @@ -0,0 +1,18 @@ +using System.Reflection; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +internal static class ObjectExtensions +{ + private static readonly Lazy MemberwiseCloneMethod = + new(() => typeof(object).GetMethod(nameof(MemberwiseClone), BindingFlags.Instance | BindingFlags.NonPublic)!, + LazyThreadSafetyMode.ExecutionAndPublication); + + public static T MemberwiseClone(this T source) + where T : class + { + ArgumentNullException.ThrowIfNull(source); + + return (T)MemberwiseCloneMethod.Value.Invoke(source, null)!; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiApplicationBuilderEvents.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiApplicationBuilderEvents.cs new file mode 100644 index 0000000000..b9cfddd772 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiApplicationBuilderEvents.cs @@ -0,0 +1,23 @@ +using JsonApiDotNetCore.Configuration; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +internal sealed class OpenApiApplicationBuilderEvents : IJsonApiApplicationBuilderEvents +{ + private readonly IJsonApiOptions _options; + private readonly IJsonApiRequestAccessor _requestAccessor; + + public OpenApiApplicationBuilderEvents(IJsonApiOptions options, IJsonApiRequestAccessor requestAccessor) + { + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(requestAccessor); + + _options = options; + _requestAccessor = requestAccessor; + } + + public void ResourceGraphBuilt(IResourceGraph resourceGraph) + { + _options.SerializerOptions.Converters.Add(new OpenApiResourceObjectConverter(resourceGraph, _requestAccessor)); + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiContentNegotiator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiContentNegotiator.cs new file mode 100644 index 0000000000..2678cb122e --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiContentNegotiator.cs @@ -0,0 +1,71 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Middleware; +using Microsoft.AspNetCore.Http; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +internal sealed class OpenApiContentNegotiator(IJsonApiOptions options, IHttpContextAccessor httpContextAccessor) + : JsonApiContentNegotiator(options, httpContextAccessor) +{ + private readonly IJsonApiOptions _options = options; + + protected override JsonApiMediaType? GetDefaultMediaType(IReadOnlyList possibleMediaTypes, JsonApiMediaType? requestMediaType) + { + if (requestMediaType != null && possibleMediaTypes.Contains(requestMediaType)) + { + // Bug workaround: NSwag doesn't send an Accept header when only non-success responses define a Content-Type. + // This occurs on POST/PATCH/DELETE at a JSON:API relationships endpoint. + return requestMediaType; + } + + return base.GetDefaultMediaType(possibleMediaTypes, requestMediaType); + } + + protected override IReadOnlyList GetPossibleMediaTypes() + { + List mediaTypes = []; + + // JSON:API compliant entries come after relaxed entries, which makes them less likely to be selected. + // This improves compatibility with client generators, which often generate broken code due to the double quotes. + + if (IsOperationsEndpoint()) + { + if (_options.Extensions.Contains(JsonApiMediaTypeExtension.RelaxedAtomicOperations)) + { + mediaTypes.Add(JsonApiMediaType.RelaxedAtomicOperations); + } + + if (_options.Extensions.Contains(JsonApiMediaTypeExtension.AtomicOperations)) + { + mediaTypes.Add(JsonApiMediaType.AtomicOperations); + } + + if (_options.Extensions.Contains(JsonApiMediaTypeExtension.RelaxedAtomicOperations) && + _options.Extensions.Contains(OpenApiMediaTypeExtension.RelaxedOpenApi)) + { + mediaTypes.Add(OpenApiMediaTypes.RelaxedAtomicOperationsWithRelaxedOpenApi); + } + + if (_options.Extensions.Contains(JsonApiMediaTypeExtension.AtomicOperations) && _options.Extensions.Contains(OpenApiMediaTypeExtension.OpenApi)) + { + mediaTypes.Add(OpenApiMediaTypes.AtomicOperationsWithOpenApi); + } + } + else + { + if (_options.Extensions.Contains(OpenApiMediaTypeExtension.RelaxedOpenApi)) + { + mediaTypes.Add(OpenApiMediaTypes.RelaxedOpenApi); + } + + if (_options.Extensions.Contains(OpenApiMediaTypeExtension.OpenApi)) + { + mediaTypes.Add(OpenApiMediaTypes.OpenApi); + } + + mediaTypes.Add(JsonApiMediaType.Default); + } + + return mediaTypes.AsReadOnly(); + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiDescriptionLinkProvider.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiDescriptionLinkProvider.cs new file mode 100644 index 0000000000..278c2154a9 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiDescriptionLinkProvider.cs @@ -0,0 +1,41 @@ +using JsonApiDotNetCore.Serialization.Response; +using Microsoft.Extensions.Options; +using Swashbuckle.AspNetCore.Swagger; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +/// +/// Provides the OpenAPI URL for the "describedby" link in https://jsonapi.org/format/#document-top-level. +/// +internal sealed class OpenApiDescriptionLinkProvider : IDocumentDescriptionLinkProvider +{ + private readonly IOptionsMonitor _swaggerGeneratorOptionsMonitor; + private readonly IOptionsMonitor _swaggerOptionsMonitor; + + public OpenApiDescriptionLinkProvider(IOptionsMonitor swaggerGeneratorOptionsMonitor, + IOptionsMonitor swaggerOptionsMonitor) + { + ArgumentNullException.ThrowIfNull(swaggerGeneratorOptionsMonitor); + ArgumentNullException.ThrowIfNull(swaggerOptionsMonitor); + + _swaggerGeneratorOptionsMonitor = swaggerGeneratorOptionsMonitor; + _swaggerOptionsMonitor = swaggerOptionsMonitor; + } + + /// + public string? GetUrl() + { + SwaggerGeneratorOptions swaggerGeneratorOptions = _swaggerGeneratorOptionsMonitor.CurrentValue; + + if (swaggerGeneratorOptions.SwaggerDocs.Count > 0) + { + string latestVersionDocumentName = swaggerGeneratorOptions.SwaggerDocs.Last().Key; + + SwaggerOptions swaggerOptions = _swaggerOptionsMonitor.CurrentValue; + return swaggerOptions.RouteTemplate.Replace("{documentName}", latestVersionDocumentName).Replace("{extension:regex(^(json|ya?ml)$)}", "json"); + } + + return null; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiEndpointConvention.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiEndpointConvention.cs new file mode 100644 index 0000000000..75649b85a8 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiEndpointConvention.cs @@ -0,0 +1,348 @@ +using System.Net; +using System.Reflection; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; +using JsonApiDotNetCore.Resources.Annotations; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ApplicationModels; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +/// +/// Sets metadata on controllers for OpenAPI documentation generation by Swagger. Only targets JsonApiDotNetCore controllers. +/// +internal sealed class OpenApiEndpointConvention : IActionModelConvention +{ + private readonly IControllerResourceMapping _controllerResourceMapping; + private readonly IJsonApiOptions _options; + + public OpenApiEndpointConvention(IControllerResourceMapping controllerResourceMapping, IJsonApiOptions options) + { + ArgumentNullException.ThrowIfNull(controllerResourceMapping); + ArgumentNullException.ThrowIfNull(options); + + _controllerResourceMapping = controllerResourceMapping; + _options = options; + } + + public void Apply(ActionModel action) + { + ArgumentNullException.ThrowIfNull(action); + + JsonApiEndpointWrapper endpoint = JsonApiEndpointWrapper.FromActionModel(action); + + if (endpoint.IsUnknown) + { + // Not a JSON:API controller, or a non-standard action method in a JSON:API controller. + // None of these are yet implemented, so hide them to avoid downstream crashes. + action.ApiExplorer.IsVisible = false; + return; + } + + ResourceType? resourceType = _controllerResourceMapping.GetResourceTypeForController(action.Controller.ControllerType); + + if (ShouldSuppressEndpoint(endpoint, resourceType)) + { + action.ApiExplorer.IsVisible = false; + return; + } + + SetResponseMetadata(action, endpoint, resourceType); + SetRequestMetadata(action, endpoint); + } + + private bool ShouldSuppressEndpoint(JsonApiEndpointWrapper endpoint, ResourceType? resourceType) + { + if (resourceType == null) + { + return false; + } + + if (!IsEndpointAvailable(endpoint.Value, resourceType)) + { + return true; + } + + if (IsSecondaryOrRelationshipEndpoint(endpoint.Value)) + { + if (resourceType.Relationships.Count == 0) + { + return true; + } + + if (endpoint.Value is JsonApiEndpoints.DeleteRelationship or JsonApiEndpoints.PostRelationship) + { + return !resourceType.Relationships.OfType().Any(); + } + } + + return false; + } + + private static bool IsEndpointAvailable(JsonApiEndpoints endpoint, ResourceType resourceType) + { + JsonApiEndpoints availableEndpoints = GetGeneratedControllerEndpoints(resourceType); + + if (availableEndpoints == JsonApiEndpoints.None) + { + // Auto-generated controllers are disabled, so we can't know what to hide. + // It is assumed that a handwritten JSON:API controller only provides action methods for what it supports. + // To accomplish that, derive from BaseJsonApiController instead of JsonApiController. + return true; + } + + // For an overridden JSON:API action method in a partial class to show up, it's flag must be turned on in [Resource]. + // Otherwise, it is considered to be an action method that throws because the endpoint is unavailable. + return IncludesEndpoint(endpoint, availableEndpoints); + } + + private static bool IncludesEndpoint(JsonApiEndpoints endpoint, JsonApiEndpoints availableEndpoints) + { + bool? isIncluded = null; + + if (endpoint == JsonApiEndpoints.GetCollection) + { + isIncluded = availableEndpoints.HasFlag(JsonApiEndpoints.GetCollection); + } + else if (endpoint == JsonApiEndpoints.GetSingle) + { + isIncluded = availableEndpoints.HasFlag(JsonApiEndpoints.GetSingle); + } + else if (endpoint == JsonApiEndpoints.GetSecondary) + { + isIncluded = availableEndpoints.HasFlag(JsonApiEndpoints.GetSecondary); + } + else if (endpoint == JsonApiEndpoints.GetRelationship) + { + isIncluded = availableEndpoints.HasFlag(JsonApiEndpoints.GetRelationship); + } + else if (endpoint == JsonApiEndpoints.Post) + { + isIncluded = availableEndpoints.HasFlag(JsonApiEndpoints.Post); + } + else if (endpoint == JsonApiEndpoints.PostRelationship) + { + isIncluded = availableEndpoints.HasFlag(JsonApiEndpoints.PostRelationship); + } + else if (endpoint == JsonApiEndpoints.Patch) + { + isIncluded = availableEndpoints.HasFlag(JsonApiEndpoints.Patch); + } + else if (endpoint == JsonApiEndpoints.PatchRelationship) + { + isIncluded = availableEndpoints.HasFlag(JsonApiEndpoints.PatchRelationship); + } + else if (endpoint == JsonApiEndpoints.Delete) + { + isIncluded = availableEndpoints.HasFlag(JsonApiEndpoints.Delete); + } + else if (endpoint == JsonApiEndpoints.DeleteRelationship) + { + isIncluded = availableEndpoints.HasFlag(JsonApiEndpoints.DeleteRelationship); + } + + ConsistencyGuard.ThrowIf(isIncluded == null); + return isIncluded.Value; + } + + private static JsonApiEndpoints GetGeneratedControllerEndpoints(ResourceType resourceType) + { + var resourceAttribute = resourceType.ClrType.GetCustomAttribute(); + return resourceAttribute?.GenerateControllerEndpoints ?? JsonApiEndpoints.None; + } + + private static bool IsSecondaryOrRelationshipEndpoint(JsonApiEndpoints endpoint) + { + return endpoint is JsonApiEndpoints.GetSecondary or JsonApiEndpoints.GetRelationship or JsonApiEndpoints.PostRelationship or + JsonApiEndpoints.PatchRelationship or JsonApiEndpoints.DeleteRelationship; + } + + private void SetResponseMetadata(ActionModel action, JsonApiEndpointWrapper endpoint, ResourceType? resourceType) + { + JsonApiMediaType mediaType = GetMediaTypeForEndpoint(endpoint); + action.Filters.Add(new ProducesAttribute(mediaType.ToString())); + + foreach (HttpStatusCode statusCode in GetSuccessStatusCodesForEndpoint(endpoint)) + { + // The return type is set later by JsonApiActionDescriptorCollectionProvider. + action.Filters.Add(new ProducesResponseTypeAttribute((int)statusCode)); + } + + foreach (HttpStatusCode statusCode in GetErrorStatusCodesForEndpoint(endpoint, resourceType)) + { + action.Filters.Add(new ProducesResponseTypeAttribute(typeof(ErrorResponseDocument), (int)statusCode)); + } + } + + private JsonApiMediaType GetMediaTypeForEndpoint(JsonApiEndpointWrapper endpoint) + { + return endpoint.IsAtomicOperationsEndpoint ? OpenApiMediaTypes.RelaxedAtomicOperationsWithRelaxedOpenApi : OpenApiMediaTypes.RelaxedOpenApi; + } + + private static HttpStatusCode[] GetSuccessStatusCodesForEndpoint(JsonApiEndpointWrapper endpoint) + { + if (endpoint.IsAtomicOperationsEndpoint) + { + return + [ + HttpStatusCode.OK, + HttpStatusCode.NoContent + ]; + } + + HttpStatusCode[]? statusCodes = null; + + if (endpoint.Value is JsonApiEndpoints.GetCollection or JsonApiEndpoints.GetSingle or JsonApiEndpoints.GetSecondary or JsonApiEndpoints.GetRelationship) + { + statusCodes = + [ + HttpStatusCode.OK, + HttpStatusCode.NotModified + ]; + } + else if (endpoint.Value == JsonApiEndpoints.Post) + { + statusCodes = + [ + HttpStatusCode.Created, + HttpStatusCode.NoContent + ]; + } + else if (endpoint.Value == JsonApiEndpoints.Patch) + { + statusCodes = + [ + HttpStatusCode.OK, + HttpStatusCode.NoContent + ]; + } + else if (endpoint.Value is JsonApiEndpoints.Delete or JsonApiEndpoints.PostRelationship or JsonApiEndpoints.PatchRelationship or + JsonApiEndpoints.DeleteRelationship) + { + statusCodes = [HttpStatusCode.NoContent]; + } + + ConsistencyGuard.ThrowIf(statusCodes == null); + return statusCodes; + } + + private HttpStatusCode[] GetErrorStatusCodesForEndpoint(JsonApiEndpointWrapper endpoint, ResourceType? resourceType) + { + if (endpoint.IsAtomicOperationsEndpoint) + { + return + [ + HttpStatusCode.BadRequest, + HttpStatusCode.Forbidden, + HttpStatusCode.NotFound, + HttpStatusCode.Conflict, + HttpStatusCode.UnprocessableEntity + ]; + } + + // Condition doesn't apply to atomic operations, because Forbidden is also used when an operation is not accessible. + ClientIdGenerationMode clientIdGeneration = resourceType?.ClientIdGeneration ?? _options.ClientIdGeneration; + + HttpStatusCode[]? statusCodes = null; + + if (endpoint.Value == JsonApiEndpoints.GetCollection) + { + statusCodes = [HttpStatusCode.BadRequest]; + } + else if (endpoint.Value is JsonApiEndpoints.GetSingle or JsonApiEndpoints.GetSecondary or JsonApiEndpoints.GetRelationship) + { + statusCodes = + [ + HttpStatusCode.BadRequest, + HttpStatusCode.NotFound + ]; + } + else if (endpoint.Value == JsonApiEndpoints.Post && clientIdGeneration == ClientIdGenerationMode.Forbidden) + { + statusCodes = + [ + HttpStatusCode.BadRequest, + HttpStatusCode.Forbidden, + HttpStatusCode.NotFound, + HttpStatusCode.Conflict, + HttpStatusCode.UnprocessableEntity + ]; + } + else if (endpoint.Value is JsonApiEndpoints.Post or JsonApiEndpoints.Patch) + { + statusCodes = + [ + HttpStatusCode.BadRequest, + HttpStatusCode.NotFound, + HttpStatusCode.Conflict, + HttpStatusCode.UnprocessableEntity + ]; + } + else if (endpoint.Value == JsonApiEndpoints.Delete) + { + statusCodes = [HttpStatusCode.NotFound]; + } + else if (endpoint.Value is JsonApiEndpoints.PostRelationship or JsonApiEndpoints.PatchRelationship or JsonApiEndpoints.DeleteRelationship) + { + statusCodes = + [ + HttpStatusCode.BadRequest, + HttpStatusCode.NotFound, + HttpStatusCode.Conflict, + HttpStatusCode.UnprocessableEntity + ]; + } + + ConsistencyGuard.ThrowIf(statusCodes == null); + return statusCodes; + } + + private void SetRequestMetadata(ActionModel action, JsonApiEndpointWrapper endpoint) + { + if (RequiresRequestBody(endpoint)) + { + JsonApiMediaType mediaType = GetMediaTypeForEndpoint(endpoint); + action.Filters.Add(new ConsumesAttribute(mediaType.ToString())); + } + } + + private static bool RequiresRequestBody(JsonApiEndpointWrapper endpoint) + { + return endpoint.IsAtomicOperationsEndpoint || endpoint.Value is JsonApiEndpoints.Post or JsonApiEndpoints.Patch or JsonApiEndpoints.PostRelationship or + JsonApiEndpoints.PatchRelationship or JsonApiEndpoints.DeleteRelationship; + } + + private sealed class JsonApiEndpointWrapper + { + private static readonly JsonApiEndpointWrapper AtomicOperations = new(true, JsonApiEndpoints.None); + + public bool IsAtomicOperationsEndpoint { get; } + public JsonApiEndpoints Value { get; } + public bool IsUnknown => !IsAtomicOperationsEndpoint && Value == JsonApiEndpoints.None; + + private JsonApiEndpointWrapper(bool isAtomicOperationsEndpoint, JsonApiEndpoints value) + { + IsAtomicOperationsEndpoint = isAtomicOperationsEndpoint; + Value = value; + } + + public static JsonApiEndpointWrapper FromActionModel(ActionModel actionModel) + { + if (EndpointResolver.Instance.IsAtomicOperationsController(actionModel.ActionMethod)) + { + return AtomicOperations; + } + + JsonApiEndpoints endpoint = EndpointResolver.Instance.GetEndpoint(actionModel.ActionMethod); + return new JsonApiEndpointWrapper(false, endpoint); + } + + public override string ToString() + { + return IsAtomicOperationsEndpoint ? "PostOperations" : Value.ToString(); + } + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiMediaTypeExtension.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiMediaTypeExtension.cs new file mode 100644 index 0000000000..64abe96e97 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiMediaTypeExtension.cs @@ -0,0 +1,14 @@ +using JsonApiDotNetCore.Middleware; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +#pragma warning disable AV1008 // Class should not be static + +internal static class OpenApiMediaTypeExtension +{ + public const string ExtensionNamespace = "openapi"; + public const string DiscriminatorPropertyName = "discriminator"; + public const string FullyQualifiedOpenApiDiscriminatorPropertyName = $"{ExtensionNamespace}:{DiscriminatorPropertyName}"; + public static readonly JsonApiMediaTypeExtension OpenApi = new("https://www.jsonapi.net/ext/openapi"); + public static readonly JsonApiMediaTypeExtension RelaxedOpenApi = new("openapi"); +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiMediaTypes.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiMediaTypes.cs new file mode 100644 index 0000000000..29cc134c34 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiMediaTypes.cs @@ -0,0 +1,21 @@ +using JsonApiDotNetCore.Middleware; + +#pragma warning disable AV1008 // Class should not be static + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +internal static class OpenApiMediaTypes +{ + public static readonly JsonApiMediaType OpenApi = new([OpenApiMediaTypeExtension.OpenApi]); + public static readonly JsonApiMediaType RelaxedOpenApi = new([OpenApiMediaTypeExtension.RelaxedOpenApi]); + + public static readonly JsonApiMediaType AtomicOperationsWithOpenApi = new([ + JsonApiMediaTypeExtension.AtomicOperations, + OpenApiMediaTypeExtension.OpenApi + ]); + + public static readonly JsonApiMediaType RelaxedAtomicOperationsWithRelaxedOpenApi = new([ + JsonApiMediaTypeExtension.RelaxedAtomicOperations, + OpenApiMediaTypeExtension.RelaxedOpenApi + ]); +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiOperationIdSelector.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiOperationIdSelector.cs new file mode 100644 index 0000000000..ed11481e27 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiOperationIdSelector.cs @@ -0,0 +1,109 @@ +using System.Reflection; +using System.Text.Json; +using Humanizer; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Relationships; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ApiExplorer; +using Microsoft.AspNetCore.Mvc.Controllers; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +internal sealed class OpenApiOperationIdSelector +{ + private const string ResourceIdTemplate = "[Method] [PrimaryResourceName]"; + private const string ResourceCollectionIdTemplate = $"{ResourceIdTemplate} Collection"; + private const string SecondaryResourceIdTemplate = $"{ResourceIdTemplate} [RelationshipName]"; + private const string RelationshipIdTemplate = $"{SecondaryResourceIdTemplate} Relationship"; + private const string AtomicOperationsIdTemplate = "[Method] Operations"; + + private static readonly Dictionary SchemaOpenTypeToOpenApiOperationIdTemplateMap = new() + { + [typeof(CollectionResponseDocument<>)] = ResourceCollectionIdTemplate, + [typeof(PrimaryResponseDocument<>)] = ResourceIdTemplate, + [typeof(CreateRequestDocument<>)] = ResourceIdTemplate, + [typeof(UpdateRequestDocument<>)] = ResourceIdTemplate, + [typeof(void)] = ResourceIdTemplate, + [typeof(SecondaryResponseDocument<>)] = SecondaryResourceIdTemplate, + [typeof(NullableSecondaryResponseDocument<>)] = SecondaryResourceIdTemplate, + [typeof(IdentifierCollectionResponseDocument<>)] = RelationshipIdTemplate, + [typeof(IdentifierResponseDocument<>)] = RelationshipIdTemplate, + [typeof(NullableIdentifierResponseDocument<>)] = RelationshipIdTemplate, + [typeof(ToOneInRequest<>)] = RelationshipIdTemplate, + [typeof(NullableToOneInRequest<>)] = RelationshipIdTemplate, + [typeof(ToManyInRequest<>)] = RelationshipIdTemplate, + [typeof(OperationsRequestDocument)] = AtomicOperationsIdTemplate + }; + + private readonly IControllerResourceMapping _controllerResourceMapping; + private readonly IJsonApiOptions _options; + + public OpenApiOperationIdSelector(IControllerResourceMapping controllerResourceMapping, IJsonApiOptions options) + { + ArgumentNullException.ThrowIfNull(controllerResourceMapping); + ArgumentNullException.ThrowIfNull(options); + + _controllerResourceMapping = controllerResourceMapping; + _options = options; + } + + public string GetOpenApiOperationId(ApiDescription endpoint) + { + ArgumentNullException.ThrowIfNull(endpoint); + + MethodInfo actionMethod = endpoint.ActionDescriptor.GetActionMethod(); + ResourceType? primaryResourceType = _controllerResourceMapping.GetResourceTypeForController(actionMethod.ReflectedType); + + string template = GetTemplate(endpoint); + return ApplyTemplate(template, primaryResourceType, endpoint); + } + + private static string GetTemplate(ApiDescription endpoint) + { + Type bodyType = GetBodyType(endpoint); + ConsistencyGuard.ThrowIf(!SchemaOpenTypeToOpenApiOperationIdTemplateMap.TryGetValue(bodyType, out string? template)); + return template; + } + + private static Type GetBodyType(ApiDescription endpoint) + { + var producesResponseTypeAttribute = endpoint.ActionDescriptor.GetFilterMetadata(); + ConsistencyGuard.ThrowIf(producesResponseTypeAttribute == null); + + ControllerParameterDescriptor? requestBodyDescriptor = endpoint.ActionDescriptor.GetBodyParameterDescriptor(); + Type bodyType = (requestBodyDescriptor?.ParameterType ?? producesResponseTypeAttribute.Type).ConstructedToOpenType(); + + if (bodyType == typeof(CollectionResponseDocument<>) && endpoint.ParameterDescriptions.Count > 0) + { + bodyType = typeof(SecondaryResponseDocument<>); + } + + return bodyType; + } + + private string ApplyTemplate(string openApiOperationIdTemplate, ResourceType? resourceType, ApiDescription endpoint) + { + ConsistencyGuard.ThrowIf(endpoint.RelativePath == null); + ConsistencyGuard.ThrowIf(endpoint.HttpMethod == null); + + string method = endpoint.HttpMethod.ToLowerInvariant(); + string relationshipName = openApiOperationIdTemplate.Contains("[RelationshipName]") ? endpoint.RelativePath.Split('/').Last() : string.Empty; + + // @formatter:wrap_chained_method_calls chop_always + // @formatter:wrap_before_first_method_call true + + string pascalCaseOpenApiOperationId = openApiOperationIdTemplate + .Replace("[Method]", method) + .Replace("[PrimaryResourceName]", resourceType?.PublicName.Singularize()) + .Replace("[RelationshipName]", relationshipName) + .Pascalize(); + + // @formatter:wrap_before_first_method_call true restore + // @formatter:wrap_chained_method_calls restore + + JsonNamingPolicy? namingPolicy = _options.SerializerOptions.PropertyNamingPolicy; + return namingPolicy != null ? namingPolicy.ConvertName(pascalCaseOpenApiOperationId) : pascalCaseOpenApiOperationId; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiResourceObjectConverter.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiResourceObjectConverter.cs new file mode 100644 index 0000000000..dd7c9503e7 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiResourceObjectConverter.cs @@ -0,0 +1,106 @@ +using System.Net; +using System.Text.Json; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Errors; +using JsonApiDotNetCore.Serialization.JsonConverters; +using JsonApiDotNetCore.Serialization.Objects; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +internal sealed class OpenApiResourceObjectConverter : ResourceObjectConverter +{ + private readonly IJsonApiRequestAccessor _requestAccessor; + + private bool HasOpenApiExtension + { + get + { + if (_requestAccessor.Current == null) + { + return false; + } + + return _requestAccessor.Current.Extensions.Contains(OpenApiMediaTypeExtension.OpenApi) || + _requestAccessor.Current.Extensions.Contains(OpenApiMediaTypeExtension.RelaxedOpenApi); + } + } + + public OpenApiResourceObjectConverter(IResourceGraph resourceGraph, IJsonApiRequestAccessor requestAccessor) + : base(resourceGraph) + { + ArgumentNullException.ThrowIfNull(requestAccessor); + + _requestAccessor = requestAccessor; + } + + private protected override void ValidateExtensionInAttributes(string extensionNamespace, string extensionName, ResourceType resourceType, + Utf8JsonReader reader) + { + if (IsOpenApiDiscriminator(extensionNamespace, extensionName)) + { + const string jsonPointer = $"attributes/{OpenApiMediaTypeExtension.ExtensionNamespace}:{OpenApiMediaTypeExtension.DiscriminatorPropertyName}"; + ValidateOpenApiDiscriminatorValue(resourceType, jsonPointer, reader); + } + else + { + base.ValidateExtensionInAttributes(extensionNamespace, extensionName, resourceType, reader); + } + } + + private protected override void ValidateExtensionInRelationships(string extensionNamespace, string extensionName, ResourceType resourceType, + Utf8JsonReader reader) + { + if (IsOpenApiDiscriminator(extensionNamespace, extensionName)) + { + const string jsonPointer = $"relationships/{OpenApiMediaTypeExtension.ExtensionNamespace}:{OpenApiMediaTypeExtension.DiscriminatorPropertyName}"; + ValidateOpenApiDiscriminatorValue(resourceType, jsonPointer, reader); + } + else + { + base.ValidateExtensionInRelationships(extensionNamespace, extensionName, resourceType, reader); + } + } + + private protected override void WriteExtensionInAttributes(Utf8JsonWriter writer, ResourceObject value) + { + if (HasOpenApiExtension) + { + writer.WriteString(OpenApiMediaTypeExtension.FullyQualifiedOpenApiDiscriminatorPropertyName, value.Type); + } + } + + private protected override void WriteExtensionInRelationships(Utf8JsonWriter writer, ResourceObject value) + { + if (HasOpenApiExtension) + { + writer.WriteString(OpenApiMediaTypeExtension.FullyQualifiedOpenApiDiscriminatorPropertyName, value.Type); + } + } + + private bool IsOpenApiDiscriminator(string extensionNamespace, string extensionName) + { + return HasOpenApiExtension && extensionNamespace == OpenApiMediaTypeExtension.ExtensionNamespace && + extensionName == OpenApiMediaTypeExtension.DiscriminatorPropertyName; + } + + private static void ValidateOpenApiDiscriminatorValue(ResourceType resourceType, string relativeJsonPointer, Utf8JsonReader reader) + { + string? discriminatorValue = reader.GetString(); + + if (discriminatorValue != resourceType.PublicName) + { + var jsonApiException = new JsonApiException(new ErrorObject(HttpStatusCode.Conflict) + { + Title = "Incompatible resource type found.", + Detail = + $"Expected {OpenApiMediaTypeExtension.FullyQualifiedOpenApiDiscriminatorPropertyName} with value '{resourceType.PublicName}' instead of '{discriminatorValue}'.", + Source = new ErrorSource + { + Pointer = relativeJsonPointer + } + }); + + CapturedThrow(jsonApiException); + } + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiSchemaExtensions.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiSchemaExtensions.cs new file mode 100644 index 0000000000..10095834b2 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiSchemaExtensions.cs @@ -0,0 +1,48 @@ +using Microsoft.OpenApi.Models; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +internal static class OpenApiSchemaExtensions +{ + public static void ReorderProperties(this OpenApiSchema fullSchema, IEnumerable propertyNamesInOrder) + { + ArgumentNullException.ThrowIfNull(fullSchema); + ArgumentNullException.ThrowIfNull(propertyNamesInOrder); + + var propertiesInOrder = new Dictionary(); + + foreach (string propertyName in propertyNamesInOrder) + { + if (fullSchema.Properties.TryGetValue(propertyName, out OpenApiSchema? schema)) + { + propertiesInOrder.Add(propertyName, schema); + } + } + + ConsistencyGuard.ThrowIf(fullSchema.Properties.Count != propertiesInOrder.Count); + + fullSchema.Properties = propertiesInOrder; + } + + public static OpenApiSchema WrapInExtendedSchema(this OpenApiSchema source) + { + ArgumentNullException.ThrowIfNull(source); + + return new OpenApiSchema + { + AllOf = [source] + }; + } + + public static OpenApiSchema UnwrapLastExtendedSchema(this OpenApiSchema source) + { + ArgumentNullException.ThrowIfNull(source); + + if (source.AllOf is { Count: > 0 }) + { + return source.AllOf.Last(); + } + + return source; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ParameterInfoWrapper.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ParameterInfoWrapper.cs new file mode 100644 index 0000000000..a785de0452 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ParameterInfoWrapper.cs @@ -0,0 +1,78 @@ +using System.Reflection; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +/// +/// Used for parameters in action method expansion. Changes the parameter name and type, while still using all metadata of the underlying non-expanded +/// parameter. +/// +internal sealed class ParameterInfoWrapper : ParameterInfo +{ + private readonly ParameterInfo _innerParameter; + + public override ParameterAttributes Attributes => _innerParameter.Attributes; + public override IEnumerable CustomAttributes => _innerParameter.CustomAttributes; + public override object? DefaultValue => _innerParameter.DefaultValue; + public override bool HasDefaultValue => _innerParameter.HasDefaultValue; + public override MemberInfo Member => _innerParameter.Member; + public override int MetadataToken => _innerParameter.MetadataToken; + public override string? Name { get; } + public override Type ParameterType { get; } + public override int Position => _innerParameter.Position; + public override object? RawDefaultValue => _innerParameter.RawDefaultValue; + + public ParameterInfoWrapper(ParameterInfo innerParameter, Type overriddenParameterType, string? overriddenName) + { + ArgumentNullException.ThrowIfNull(innerParameter); + ArgumentNullException.ThrowIfNull(overriddenParameterType); + + _innerParameter = innerParameter; + ParameterType = overriddenParameterType; + Name = overriddenName; + } + + public override object[] GetCustomAttributes(bool inherit) + { + return _innerParameter.GetCustomAttributes(inherit); + } + + public override object[] GetCustomAttributes(Type attributeType, bool inherit) + { + return _innerParameter.GetCustomAttributes(attributeType, inherit); + } + + public override bool IsDefined(Type attributeType, bool inherit) + { + return _innerParameter.IsDefined(attributeType, inherit); + } + + public override bool Equals(object? obj) + { + return _innerParameter.Equals(obj); + } + + public override int GetHashCode() + { + return _innerParameter.GetHashCode(); + } + + public override string ToString() + { + return _innerParameter.ToString(); + } + + public override IList GetCustomAttributesData() + { + return _innerParameter.GetCustomAttributesData(); + } + + public override Type[] GetOptionalCustomModifiers() + { + return _innerParameter.GetOptionalCustomModifiers(); + } + + public override Type[] GetRequiredCustomModifiers() + { + return _innerParameter.GetRequiredCustomModifiers(); + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ResourceFieldValidationMetadataProvider.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ResourceFieldValidationMetadataProvider.cs new file mode 100644 index 0000000000..f0ce60c730 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ResourceFieldValidationMetadataProvider.cs @@ -0,0 +1,81 @@ +using System.ComponentModel.DataAnnotations; +using System.Reflection; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Resources.Annotations; +using Microsoft.AspNetCore.Mvc.ModelBinding; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +internal sealed class ResourceFieldValidationMetadataProvider +{ + private readonly IJsonApiOptions _options; + private readonly IModelMetadataProvider _modelMetadataProvider; + + public ResourceFieldValidationMetadataProvider(IJsonApiOptions options, IModelMetadataProvider modelMetadataProvider) + { + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(modelMetadataProvider); + + _options = options; + _modelMetadataProvider = modelMetadataProvider; + } + + public bool IsNullable(ResourceFieldAttribute field) + { + ArgumentNullException.ThrowIfNull(field); + + if (field is HasManyAttribute) + { + return false; + } + + bool hasRequiredAttribute = field.Property.HasAttribute(); + + if (_options.ValidateModelState && hasRequiredAttribute) + { + return false; + } + + NullabilityInfoContext nullabilityContext = new(); + NullabilityInfo nullabilityInfo = nullabilityContext.Create(field.Property); + return nullabilityInfo.ReadState != NullabilityState.NotNull; + } + + public bool IsRequired(ResourceFieldAttribute field) + { + ArgumentNullException.ThrowIfNull(field); + + bool hasRequiredAttribute = field.Property.HasAttribute(); + + if (!_options.ValidateModelState) + { + return hasRequiredAttribute; + } + + if (field is HasManyAttribute) + { + return false; + } + + NullabilityInfoContext nullabilityContext = new(); + NullabilityInfo nullabilityInfo = nullabilityContext.Create(field.Property); + bool isRequiredValueType = field.Property.PropertyType.IsValueType && hasRequiredAttribute && nullabilityInfo.ReadState == NullabilityState.NotNull; + + if (isRequiredValueType) + { + // Special case: ASP.NET ModelState Validation effectively ignores value types with [Required]. + return false; + } + + return IsModelStateValidationRequired(field); + } + + private bool IsModelStateValidationRequired(ResourceFieldAttribute field) + { + ModelMetadata modelMetadata = _modelMetadataProvider.GetMetadataForProperty(field.Type.ClrType, field.Property.Name); + + // Non-nullable reference types are implicitly required, unless SuppressImplicitRequiredAttributeForNonNullableReferenceTypes is set. + return modelMetadata.ValidatorMetadata.Any(validatorMetadata => validatorMetadata is RequiredAttribute); + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerationTracer.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerationTracer.cs new file mode 100644 index 0000000000..6dbd6bb2f3 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerationTracer.cs @@ -0,0 +1,153 @@ +using JsonApiDotNetCore.Resources.Annotations; +using JsonApiDotNetCore.Serialization.Objects; +using Microsoft.Extensions.Logging; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +/// +/// Enables to log recursive component schema generation at trace level. +/// +internal sealed partial class SchemaGenerationTracer +{ + private readonly ILoggerFactory _loggerFactory; + + public SchemaGenerationTracer(ILoggerFactory loggerFactory) + { + ArgumentNullException.ThrowIfNull(loggerFactory); + + _loggerFactory = loggerFactory; + } + + public ISchemaGenerationTraceScope TraceStart(object generator) + { + ArgumentNullException.ThrowIfNull(generator); + + return InnerTraceStart(generator, () => "(none)"); + } + + public ISchemaGenerationTraceScope TraceStart(object generator, Type schemaType) + { + ArgumentNullException.ThrowIfNull(generator); + ArgumentNullException.ThrowIfNull(schemaType); + + return InnerTraceStart(generator, () => GetSchemaTypeName(schemaType)); + } + + public ISchemaGenerationTraceScope TraceStart(object generator, AtomicOperationCode operationCode) + { + ArgumentNullException.ThrowIfNull(generator); + + return InnerTraceStart(generator, () => $"{nameof(AtomicOperationCode)}.{operationCode}"); + } + + public ISchemaGenerationTraceScope TraceStart(object generator, RelationshipAttribute relationship) + { + ArgumentNullException.ThrowIfNull(generator); + ArgumentNullException.ThrowIfNull(relationship); + + return InnerTraceStart(generator, + () => $"{GetSchemaTypeName(relationship.GetType())}({GetSchemaTypeName(relationship.LeftType.ClrType)}.{relationship.Property.Name})"); + } + + public ISchemaGenerationTraceScope TraceStart(object generator, Type schemaOpenType, RelationshipAttribute relationship) + { + ArgumentNullException.ThrowIfNull(generator); + ArgumentNullException.ThrowIfNull(schemaOpenType); + ArgumentNullException.ThrowIfNull(relationship); + + return InnerTraceStart(generator, + () => + $"{GetSchemaTypeName(schemaOpenType)} with {GetSchemaTypeName(relationship.GetType())}({GetSchemaTypeName(relationship.LeftType.ClrType)}.{relationship.Property.Name})"); + } + + private ISchemaGenerationTraceScope InnerTraceStart(object generator, Func getSchemaTypeName) + { + ILogger logger = _loggerFactory.CreateLogger(generator.GetType()); + + if (logger.IsEnabled(LogLevel.Trace)) + { + string schemaTypeName = getSchemaTypeName(); + return new SchemaGenerationTraceScope(logger, schemaTypeName); + } + + return DisabledSchemaGenerationTraceScope.Instance; + } + + private static string GetSchemaTypeName(Type type) + { + if (type.IsConstructedGenericType) + { + string typeArguments = string.Join(',', type.GetGenericArguments().Select(GetSchemaTypeName)); + int arityIndex = type.Name.IndexOf('`'); + return $"{type.Name[..arityIndex]}<{typeArguments}>"; + } + + return type.Name; + } + + private sealed partial class SchemaGenerationTraceScope : ISchemaGenerationTraceScope + { + private static readonly AsyncLocal RecursionDepthAsyncLocal = new(); + + private readonly ILogger _logger; + private readonly string _schemaTypeName; + private string? _schemaId; + + public SchemaGenerationTraceScope(ILogger logger, string schemaTypeName) + { + ArgumentNullException.ThrowIfNull(logger); + ArgumentNullException.ThrowIfNull(schemaTypeName); + + _logger = logger; + _schemaTypeName = schemaTypeName; + + RecursionDepthAsyncLocal.Value++; + LogStarted(RecursionDepthAsyncLocal.Value, _schemaTypeName); + } + + public void TraceSucceeded(string schemaId) + { + _schemaId = schemaId; + } + + public void Dispose() + { + if (_schemaId != null) + { + LogSucceeded(RecursionDepthAsyncLocal.Value, _schemaTypeName, _schemaId); + } + else + { + LogFailed(RecursionDepthAsyncLocal.Value, _schemaTypeName); + } + + RecursionDepthAsyncLocal.Value--; + } + + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, Message = "({Depth:D2}) Started for {SchemaTypeName}.")] + private partial void LogStarted(int depth, string schemaTypeName); + + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, Message = "({Depth:D2}) Generated '{SchemaId}' from {SchemaTypeName}.")] + private partial void LogSucceeded(int depth, string schemaTypeName, string schemaId); + + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, Message = "({Depth:D2}) Failed for {SchemaTypeName}.")] + private partial void LogFailed(int depth, string schemaTypeName); + } + + private sealed class DisabledSchemaGenerationTraceScope : ISchemaGenerationTraceScope + { + public static DisabledSchemaGenerationTraceScope Instance { get; } = new(); + + private DisabledSchemaGenerationTraceScope() + { + } + + public void TraceSucceeded(string schemaId) + { + } + + public void Dispose() + { + } + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/AtomicOperationCodeSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/AtomicOperationCodeSchemaGenerator.cs new file mode 100644 index 0000000000..78a25da441 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/AtomicOperationCodeSchemaGenerator.cs @@ -0,0 +1,55 @@ +using JsonApiDotNetCore.Serialization.Objects; +using Microsoft.OpenApi.Any; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; + +internal sealed class AtomicOperationCodeSchemaGenerator +{ + private readonly SchemaGenerationTracer _schemaGenerationTracer; + private readonly JsonApiSchemaIdSelector _schemaIdSelector; + + public AtomicOperationCodeSchemaGenerator(SchemaGenerationTracer schemaGenerationTracer, JsonApiSchemaIdSelector schemaIdSelector) + { + ArgumentNullException.ThrowIfNull(schemaGenerationTracer); + ArgumentNullException.ThrowIfNull(schemaIdSelector); + + _schemaGenerationTracer = schemaGenerationTracer; + _schemaIdSelector = schemaIdSelector; + } + + public OpenApiSchema GenerateSchema(AtomicOperationCode operationCode, SchemaRepository schemaRepository) + { + ArgumentNullException.ThrowIfNull(schemaRepository); + + string schemaId = _schemaIdSelector.GetAtomicOperationCodeSchemaId(operationCode); + + if (schemaRepository.Schemas.ContainsKey(schemaId)) + { + return new OpenApiSchema + { + Reference = new OpenApiReference + { + Id = schemaId, + Type = ReferenceType.Schema + } + }; + } + + using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, operationCode); + + string enumValue = operationCode.ToString().ToLowerInvariant(); + + var fullSchema = new OpenApiSchema + { + Type = "string", + Enum = [new OpenApiString(enumValue)] + }; + + OpenApiSchema referenceSchema = schemaRepository.AddDefinition(schemaId, fullSchema); + + traceScope.TraceSucceeded(schemaId); + return referenceSchema; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/DataContainerSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/DataContainerSchemaGenerator.cs new file mode 100644 index 0000000000..c4b41dd0f5 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/DataContainerSchemaGenerator.cs @@ -0,0 +1,109 @@ +using System.Reflection; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; + +/// +/// Generates the reference schema for the Data property in a request or response schema, taking schema inheritance into account. +/// +internal sealed class DataContainerSchemaGenerator +{ + private readonly SchemaGenerationTracer _schemaGenerationTracer; + private readonly DataSchemaGenerator _dataSchemaGenerator; + private readonly IResourceGraph _resourceGraph; + + public DataContainerSchemaGenerator(SchemaGenerationTracer schemaGenerationTracer, DataSchemaGenerator dataSchemaGenerator, IResourceGraph resourceGraph) + { + ArgumentNullException.ThrowIfNull(schemaGenerationTracer); + ArgumentNullException.ThrowIfNull(dataSchemaGenerator); + ArgumentNullException.ThrowIfNull(resourceGraph); + + _schemaGenerationTracer = schemaGenerationTracer; + _dataSchemaGenerator = dataSchemaGenerator; + _resourceGraph = resourceGraph; + } + + public OpenApiSchema GenerateSchemaForCommonResourceDataInResponse(SchemaRepository schemaRepository) + { + ArgumentNullException.ThrowIfNull(schemaRepository); + + return _dataSchemaGenerator.GenerateSchemaForCommonData(typeof(ResourceInResponse), schemaRepository); + } + + public OpenApiSchema GenerateSchema(Type dataContainerSchemaType, ResourceType resourceType, bool forRequestSchema, bool canIncludeRelated, + SchemaRepository schemaRepository) + { + ArgumentNullException.ThrowIfNull(dataContainerSchemaType); + ArgumentNullException.ThrowIfNull(resourceType); + ArgumentNullException.ThrowIfNull(schemaRepository); + + if (schemaRepository.TryLookupByType(dataContainerSchemaType, out OpenApiSchema referenceSchemaForData)) + { + return referenceSchemaForData; + } + + Type dataConstructedType = GetElementTypeOfDataProperty(dataContainerSchemaType, resourceType); + + if (schemaRepository.TryLookupByType(dataConstructedType, out _)) + { + return referenceSchemaForData; + } + + using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, dataConstructedType); + + if (canIncludeRelated) + { + var resourceSchemaType = ResourceSchemaType.Create(dataConstructedType, _resourceGraph); + + if (resourceSchemaType.SchemaOpenType == typeof(DataInResponse<>)) + { + // Ensure all reachable related resource types in response schemas are generated upfront. + // This is needed to make includes work when not all endpoints are exposed. + GenerateReachableRelatedTypesInResponse(dataConstructedType, schemaRepository); + } + } + + referenceSchemaForData = _dataSchemaGenerator.GenerateSchema(dataConstructedType, forRequestSchema, schemaRepository); + traceScope.TraceSucceeded(referenceSchemaForData.Reference.Id); + return referenceSchemaForData; + } + + private static Type GetElementTypeOfDataProperty(Type dataContainerConstructedType, ResourceType resourceType) + { + PropertyInfo? dataProperty = dataContainerConstructedType.GetProperty("Data"); + ConsistencyGuard.ThrowIf(dataProperty == null); + + Type innerPropertyType = dataProperty.PropertyType.ConstructedToOpenType().IsAssignableTo(typeof(ICollection<>)) + ? dataProperty.PropertyType.GenericTypeArguments[0] + : dataProperty.PropertyType; + + if (innerPropertyType == typeof(ResourceInResponse)) + { + return typeof(DataInResponse<>).MakeGenericType(resourceType.ClrType); + } + + ConsistencyGuard.ThrowIf(!innerPropertyType.IsGenericType); + + return innerPropertyType; + } + + private void GenerateReachableRelatedTypesInResponse(Type dataConstructedType, SchemaRepository schemaRepository) + { + Type dataOpenType = dataConstructedType.GetGenericTypeDefinition(); + + if (dataOpenType == typeof(DataInResponse<>)) + { + var resourceSchemaType = ResourceSchemaType.Create(dataConstructedType, _resourceGraph); + + foreach (ResourceType relatedType in IncludeDependencyScanner.Instance.GetReachableRelatedTypes(resourceSchemaType.ResourceType)) + { + Type resourceDataConstructedType = typeof(DataInResponse<>).MakeGenericType(relatedType.ClrType); + _ = _dataSchemaGenerator.GenerateSchema(resourceDataConstructedType, false, schemaRepository); + } + } + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/DataSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/DataSchemaGenerator.cs new file mode 100644 index 0000000000..4d7783f780 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/DataSchemaGenerator.cs @@ -0,0 +1,641 @@ +using System.Collections.Concurrent; +using System.Reflection; +using System.Runtime.CompilerServices; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; +using Microsoft.OpenApi.Any; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; + +internal sealed class DataSchemaGenerator +{ + // Workaround for bug at https://github.com/microsoft/kiota/issues/2432#issuecomment-2436625836. + private static readonly bool RepeatDiscriminatorInResponseDerivedTypes = bool.Parse(bool.TrueString); + + private static readonly ConcurrentDictionary UltimateBaseResourceTypeCache = []; + + private static readonly string[] DataPropertyNamesInOrder = + [ + JsonApiPropertyName.Type, + JsonApiPropertyName.Id, + JsonApiPropertyName.Lid, + JsonApiPropertyName.Attributes, + JsonApiPropertyName.Relationships, + JsonApiPropertyName.Links, + JsonApiPropertyName.Meta + ]; + + private readonly SchemaGenerationTracer _schemaGenerationTracer; + private readonly SchemaGenerator _defaultSchemaGenerator; + private readonly GenerationCacheSchemaGenerator _generationCacheSchemaGenerator; + private readonly ResourceTypeSchemaGenerator _resourceTypeSchemaGenerator; + private readonly ResourceIdSchemaGenerator _resourceIdSchemaGenerator; + private readonly LinksVisibilitySchemaGenerator _linksVisibilitySchemaGenerator; + private readonly MetaSchemaGenerator _metaSchemaGenerator; + private readonly JsonApiSchemaIdSelector _schemaIdSelector; + private readonly IJsonApiOptions _options; + private readonly IResourceGraph _resourceGraph; + private readonly ResourceFieldValidationMetadataProvider _resourceFieldValidationMetadataProvider; + private readonly RelationshipTypeFactory _relationshipTypeFactory; + private readonly ResourceDocumentationReader _resourceDocumentationReader; + + public DataSchemaGenerator(SchemaGenerationTracer schemaGenerationTracer, SchemaGenerator defaultSchemaGenerator, + GenerationCacheSchemaGenerator generationCacheSchemaGenerator, ResourceTypeSchemaGenerator resourceTypeSchemaGenerator, + ResourceIdSchemaGenerator resourceIdSchemaGenerator, LinksVisibilitySchemaGenerator linksVisibilitySchemaGenerator, + MetaSchemaGenerator metaSchemaGenerator, JsonApiSchemaIdSelector schemaIdSelector, IJsonApiOptions options, IResourceGraph resourceGraph, + ResourceFieldValidationMetadataProvider resourceFieldValidationMetadataProvider, RelationshipTypeFactory relationshipTypeFactory, + ResourceDocumentationReader resourceDocumentationReader) + { + ArgumentNullException.ThrowIfNull(schemaGenerationTracer); + ArgumentNullException.ThrowIfNull(defaultSchemaGenerator); + ArgumentNullException.ThrowIfNull(generationCacheSchemaGenerator); + ArgumentNullException.ThrowIfNull(resourceTypeSchemaGenerator); + ArgumentNullException.ThrowIfNull(resourceIdSchemaGenerator); + ArgumentNullException.ThrowIfNull(linksVisibilitySchemaGenerator); + ArgumentNullException.ThrowIfNull(metaSchemaGenerator); + ArgumentNullException.ThrowIfNull(schemaIdSelector); + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(resourceGraph); + ArgumentNullException.ThrowIfNull(resourceFieldValidationMetadataProvider); + ArgumentNullException.ThrowIfNull(relationshipTypeFactory); + ArgumentNullException.ThrowIfNull(resourceDocumentationReader); + + _schemaGenerationTracer = schemaGenerationTracer; + _defaultSchemaGenerator = defaultSchemaGenerator; + _generationCacheSchemaGenerator = generationCacheSchemaGenerator; + _resourceTypeSchemaGenerator = resourceTypeSchemaGenerator; + _resourceIdSchemaGenerator = resourceIdSchemaGenerator; + _linksVisibilitySchemaGenerator = linksVisibilitySchemaGenerator; + _metaSchemaGenerator = metaSchemaGenerator; + _schemaIdSelector = schemaIdSelector; + _options = options; + _resourceGraph = resourceGraph; + _resourceFieldValidationMetadataProvider = resourceFieldValidationMetadataProvider; + _relationshipTypeFactory = relationshipTypeFactory; + _resourceDocumentationReader = resourceDocumentationReader; + } + + public OpenApiSchema GenerateSchema(Type dataSchemaType, bool forRequestSchema, SchemaRepository schemaRepository) + { + // For a given resource (identifier) type, we always generate the full type hierarchy. Discriminator mappings + // are managed manually, because there's no way to intercept in the Swashbuckle recursive component schema generation. + + ArgumentNullException.ThrowIfNull(dataSchemaType); + ArgumentNullException.ThrowIfNull(schemaRepository); + + if (schemaRepository.TryLookupByType(dataSchemaType, out OpenApiSchema referenceSchemaForData)) + { + return referenceSchemaForData; + } + + var resourceSchemaType = ResourceSchemaType.Create(dataSchemaType, _resourceGraph); + ResourceType resourceType = resourceSchemaType.ResourceType; + + Type? commonDataSchemaType = GetCommonSchemaType(resourceSchemaType.SchemaOpenType); + + if (commonDataSchemaType != null) + { + _ = GenerateSchemaForCommonData(commonDataSchemaType, schemaRepository); + } + + if (resourceType.BaseType != null) + { + ResourceType ultimateBaseResourceType = GetUltimateBaseType(resourceType); + Type ultimateBaseSchemaType = ChangeResourceTypeInSchemaType(dataSchemaType, ultimateBaseResourceType); + + _ = GenerateSchema(ultimateBaseSchemaType, forRequestSchema, schemaRepository); + + return schemaRepository.LookupByType(dataSchemaType); + } + + using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, dataSchemaType); + + referenceSchemaForData = _defaultSchemaGenerator.GenerateSchema(dataSchemaType, schemaRepository); + OpenApiSchema fullSchemaForData = schemaRepository.Schemas[referenceSchemaForData.Reference.Id]; + fullSchemaForData.AdditionalPropertiesAllowed = false; + + OpenApiSchema inlineSchemaForData = fullSchemaForData.UnwrapLastExtendedSchema(); + + SetAbstract(inlineSchemaForData, resourceSchemaType); + SetResourceType(inlineSchemaForData, resourceType, schemaRepository); + AdaptResourceIdentity(inlineSchemaForData, resourceSchemaType, forRequestSchema, schemaRepository); + SetResourceId(inlineSchemaForData, resourceType, schemaRepository); + SetResourceFields(inlineSchemaForData, resourceSchemaType, forRequestSchema, schemaRepository); + SetDocumentation(fullSchemaForData, resourceType); + SetLinksVisibility(inlineSchemaForData, resourceSchemaType, schemaRepository); + + if (resourceType.IsPartOfTypeHierarchy()) + { + GenerateDataSchemasForDirectlyDerivedTypes(resourceSchemaType, forRequestSchema, schemaRepository); + } + + inlineSchemaForData.ReorderProperties(DataPropertyNamesInOrder); + + if (commonDataSchemaType != null) + { + MapInDiscriminator(resourceSchemaType, forRequestSchema, JsonApiPropertyName.Type, schemaRepository); + } + + if (RequiresRootObjectTypeInDataSchema(resourceSchemaType, forRequestSchema)) + { + fullSchemaForData.Extensions[SetSchemaTypeToObjectDocumentFilter.RequiresRootObjectTypeKey] = new OpenApiBoolean(true); + } + + traceScope.TraceSucceeded(referenceSchemaForData.Reference.Id); + return referenceSchemaForData; + } + + private static Type? GetCommonSchemaType(Type schemaOpenType) + { + StrongBox? boxedSchemaType = null; + + if (schemaOpenType == typeof(IdentifierInRequest<>)) + { + boxedSchemaType = new StrongBox(typeof(IdentifierInRequest)); + } + else if (schemaOpenType == typeof(DataInCreateRequest<>)) + { + boxedSchemaType = new StrongBox(typeof(ResourceInCreateRequest)); + } + else if (schemaOpenType == typeof(AttributesInCreateRequest<>)) + { + boxedSchemaType = new StrongBox(typeof(AttributesInCreateRequest)); + } + else if (schemaOpenType == typeof(RelationshipsInCreateRequest<>)) + { + boxedSchemaType = new StrongBox(typeof(RelationshipsInCreateRequest)); + } + else if (schemaOpenType == typeof(DataInUpdateRequest<>)) + { + boxedSchemaType = new StrongBox(typeof(ResourceInUpdateRequest)); + } + else if (schemaOpenType == typeof(AttributesInUpdateRequest<>)) + { + boxedSchemaType = new StrongBox(typeof(AttributesInUpdateRequest)); + } + else if (schemaOpenType == typeof(RelationshipsInUpdateRequest<>)) + { + boxedSchemaType = new StrongBox(typeof(RelationshipsInUpdateRequest)); + } + else if (schemaOpenType == typeof(IdentifierInResponse<>)) + { + boxedSchemaType = new StrongBox(null); + } + else if (schemaOpenType == typeof(DataInResponse<>)) + { + boxedSchemaType = new StrongBox(typeof(ResourceInResponse)); + } + else if (schemaOpenType == typeof(AttributesInResponse<>)) + { + boxedSchemaType = new StrongBox(typeof(AttributesInResponse)); + } + else if (schemaOpenType == typeof(RelationshipsInResponse<>)) + { + boxedSchemaType = new StrongBox(typeof(RelationshipsInResponse)); + } + + ConsistencyGuard.ThrowIf(boxedSchemaType == null); + return boxedSchemaType.Value; + } + + public OpenApiSchema GenerateSchemaForCommonData(Type commonDataSchemaType, SchemaRepository schemaRepository) + { + ArgumentNullException.ThrowIfNull(commonDataSchemaType); + ArgumentNullException.ThrowIfNull(schemaRepository); + + if (schemaRepository.TryLookupByType(commonDataSchemaType, out OpenApiSchema? referenceSchema)) + { + return referenceSchema; + } + + using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, commonDataSchemaType); + + OpenApiSchema referenceSchemaForResourceType = _resourceTypeSchemaGenerator.GenerateSchema(schemaRepository); + OpenApiSchema referenceSchemaForMeta = _metaSchemaGenerator.GenerateSchema(schemaRepository); + + var fullSchema = new OpenApiSchema + { + Type = "object", + Required = new SortedSet([JsonApiPropertyName.Type]), + Properties = new Dictionary + { + [JsonApiPropertyName.Type] = referenceSchemaForResourceType.WrapInExtendedSchema(), + [referenceSchemaForMeta.Reference.Id] = referenceSchemaForMeta.WrapInExtendedSchema() + }, + AdditionalPropertiesAllowed = false, + Discriminator = new OpenApiDiscriminator + { + PropertyName = JsonApiPropertyName.Type, + Mapping = new SortedDictionary(StringComparer.Ordinal) + }, + Extensions = + { + ["x-abstract"] = new OpenApiBoolean(true) + } + }; + + string schemaId = _schemaIdSelector.GetSchemaId(commonDataSchemaType); + + referenceSchema = schemaRepository.AddDefinition(schemaId, fullSchema); + schemaRepository.RegisterType(commonDataSchemaType, schemaId); + + traceScope.TraceSucceeded(schemaId); + return referenceSchema; + } + + private static ResourceType GetUltimateBaseType(ResourceType resourceType) + { + return UltimateBaseResourceTypeCache.GetOrAdd(resourceType, type => + { + ResourceType baseType = type; + + while (baseType.BaseType != null) + { + baseType = baseType.BaseType; + } + + return baseType; + }); + } + + private static Type ChangeResourceTypeInSchemaType(Type schemaType, ResourceType resourceType) + { + Type schemaOpenType = schemaType.ConstructedToOpenType(); + return schemaOpenType.MakeGenericType(resourceType.ClrType); + } + + private static void SetAbstract(OpenApiSchema fullSchema, ResourceSchemaType resourceSchemaType) + { + if (resourceSchemaType.ResourceType.ClrType.IsAbstract && resourceSchemaType.SchemaOpenType != typeof(IdentifierInRequest<>)) + { + fullSchema.Extensions["x-abstract"] = new OpenApiBoolean(true); + } + } + + private void SetResourceType(OpenApiSchema fullSchema, ResourceType resourceType, SchemaRepository schemaRepository) + { + if (fullSchema.Properties.ContainsKey(JsonApiPropertyName.Type)) + { + OpenApiSchema referenceSchema = _resourceTypeSchemaGenerator.GenerateSchema(resourceType, schemaRepository); + fullSchema.Properties[JsonApiPropertyName.Type] = referenceSchema.WrapInExtendedSchema(); + } + } + + private void AdaptResourceIdentity(OpenApiSchema fullSchema, ResourceSchemaType resourceSchemaType, bool forRequestSchema, + SchemaRepository schemaRepository) + { + if (!forRequestSchema) + { + return; + } + + bool hasAtomicOperationsEndpoint = _generationCacheSchemaGenerator.HasAtomicOperationsEndpoint(schemaRepository); + + if (!hasAtomicOperationsEndpoint) + { + fullSchema.Properties.Remove(JsonApiPropertyName.Lid); + } + + if (resourceSchemaType.SchemaOpenType == typeof(DataInCreateRequest<>)) + { + ClientIdGenerationMode clientIdGeneration = resourceSchemaType.ResourceType.ClientIdGeneration ?? _options.ClientIdGeneration; + + if (hasAtomicOperationsEndpoint) + { + if (clientIdGeneration == ClientIdGenerationMode.Forbidden) + { + fullSchema.Properties.Remove(JsonApiPropertyName.Id); + } + else if (clientIdGeneration == ClientIdGenerationMode.Required) + { + fullSchema.Properties.Remove(JsonApiPropertyName.Lid); + fullSchema.Required.Add(JsonApiPropertyName.Id); + } + } + else + { + if (clientIdGeneration == ClientIdGenerationMode.Forbidden) + { + fullSchema.Properties.Remove(JsonApiPropertyName.Id); + } + else if (clientIdGeneration == ClientIdGenerationMode.Required) + { + fullSchema.Required.Add(JsonApiPropertyName.Id); + } + } + } + else + { + if (!hasAtomicOperationsEndpoint) + { + fullSchema.Required.Add(JsonApiPropertyName.Id); + } + } + } + + private void SetResourceId(OpenApiSchema fullSchema, ResourceType resourceType, SchemaRepository schemaRepository) + { + if (fullSchema.Properties.ContainsKey(JsonApiPropertyName.Id)) + { + OpenApiSchema idSchema = _resourceIdSchemaGenerator.GenerateSchema(resourceType, schemaRepository); + fullSchema.Properties[JsonApiPropertyName.Id] = idSchema; + } + } + + private void SetResourceFields(OpenApiSchema fullSchemaForData, ResourceSchemaType resourceSchemaType, bool forRequestSchema, + SchemaRepository schemaRepository) + { + bool schemaHasFields = fullSchemaForData.Properties.ContainsKey(JsonApiPropertyName.Attributes) && + fullSchemaForData.Properties.ContainsKey(JsonApiPropertyName.Relationships); + + if (schemaHasFields) + { + var fieldSchemaBuilder = new ResourceFieldSchemaBuilder(_schemaGenerationTracer, _defaultSchemaGenerator, this, _linksVisibilitySchemaGenerator, + _resourceFieldValidationMetadataProvider, _relationshipTypeFactory, resourceSchemaType); + + SetFieldSchemaMembers(fullSchemaForData, resourceSchemaType, forRequestSchema, true, fieldSchemaBuilder, schemaRepository); + SetFieldSchemaMembers(fullSchemaForData, resourceSchemaType, forRequestSchema, false, fieldSchemaBuilder, schemaRepository); + } + } + + private void SetFieldSchemaMembers(OpenApiSchema fullSchemaForData, ResourceSchemaType resourceSchemaTypeForData, bool forRequestSchema, bool forAttributes, + ResourceFieldSchemaBuilder fieldSchemaBuilder, SchemaRepository schemaRepository) + { + string propertyNameInSchema = forAttributes ? JsonApiPropertyName.Attributes : JsonApiPropertyName.Relationships; + + OpenApiSchema referenceSchemaForFields = fullSchemaForData.Properties[propertyNameInSchema].UnwrapLastExtendedSchema(); + OpenApiSchema fullSchemaForFields = schemaRepository.Schemas[referenceSchemaForFields.Reference.Id]; + fullSchemaForFields.AdditionalPropertiesAllowed = false; + + SetAbstract(fullSchemaForFields, resourceSchemaTypeForData); + + if (forAttributes) + { + fieldSchemaBuilder.SetMembersOfAttributes(fullSchemaForFields, forRequestSchema, schemaRepository); + } + else + { + fieldSchemaBuilder.SetMembersOfRelationships(fullSchemaForFields, forRequestSchema, schemaRepository); + } + + if (fullSchemaForFields.Properties.Count == 0 && !resourceSchemaTypeForData.ResourceType.IsPartOfTypeHierarchy()) + { + fullSchemaForData.Properties.Remove(propertyNameInSchema); + schemaRepository.Schemas.Remove(referenceSchemaForFields.Reference.Id); + } + else + { + ResourceSchemaType resourceSchemaTypeForFields = + GetResourceSchemaTypeForFieldsProperty(resourceSchemaTypeForData, forAttributes ? "Attributes" : "Relationships"); + + Type? commonFieldsSchemaType = GetCommonSchemaType(resourceSchemaTypeForFields.SchemaOpenType); + ConsistencyGuard.ThrowIf(commonFieldsSchemaType == null); + + _ = GenerateSchemaForCommonFields(commonFieldsSchemaType, schemaRepository); + + MapInDiscriminator(resourceSchemaTypeForFields, forRequestSchema, OpenApiMediaTypeExtension.FullyQualifiedOpenApiDiscriminatorPropertyName, + schemaRepository); + + Type baseSchemaType; + + if (resourceSchemaTypeForFields.ResourceType.BaseType != null) + { + ResourceSchemaType resourceSchemaTypeForBase = + resourceSchemaTypeForFields.ChangeResourceType(resourceSchemaTypeForFields.ResourceType.BaseType); + + baseSchemaType = resourceSchemaTypeForBase.SchemaConstructedType; + } + else + { + baseSchemaType = commonFieldsSchemaType; + } + + OpenApiSchema referenceSchemaForBase = schemaRepository.LookupByType(baseSchemaType); + + schemaRepository.Schemas[referenceSchemaForFields.Reference.Id] = new OpenApiSchema + { + AllOf = + [ + referenceSchemaForBase, + fullSchemaForFields + ], + AdditionalPropertiesAllowed = false + }; + } + } + + private ResourceSchemaType GetResourceSchemaTypeForFieldsProperty(ResourceSchemaType resourceSchemaTypeForData, string propertyName) + { + PropertyInfo? fieldsProperty = resourceSchemaTypeForData.SchemaConstructedType.GetProperty(propertyName); + ConsistencyGuard.ThrowIf(fieldsProperty == null); + + Type fieldsConstructedType = fieldsProperty.PropertyType; + return ResourceSchemaType.Create(fieldsConstructedType, _resourceGraph); + } + + private OpenApiSchema GenerateSchemaForCommonFields(Type commonFieldsSchemaType, SchemaRepository schemaRepository) + { + if (schemaRepository.TryLookupByType(commonFieldsSchemaType, out OpenApiSchema? referenceSchema)) + { + return referenceSchema; + } + + using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, commonFieldsSchemaType); + + OpenApiSchema referenceSchemaForResourceType = _resourceTypeSchemaGenerator.GenerateSchema(schemaRepository); + + var fullSchema = new OpenApiSchema + { + Type = "object", + Required = new SortedSet([OpenApiMediaTypeExtension.FullyQualifiedOpenApiDiscriminatorPropertyName]), + Properties = new Dictionary + { + [OpenApiMediaTypeExtension.FullyQualifiedOpenApiDiscriminatorPropertyName] = referenceSchemaForResourceType.WrapInExtendedSchema() + }, + AdditionalPropertiesAllowed = false, + Discriminator = new OpenApiDiscriminator + { + PropertyName = OpenApiMediaTypeExtension.FullyQualifiedOpenApiDiscriminatorPropertyName, + Mapping = new SortedDictionary(StringComparer.Ordinal) + }, + Extensions = + { + ["x-abstract"] = new OpenApiBoolean(true) + } + }; + + string schemaId = _schemaIdSelector.GetSchemaId(commonFieldsSchemaType); + + referenceSchema = schemaRepository.AddDefinition(schemaId, fullSchema); + schemaRepository.RegisterType(commonFieldsSchemaType, schemaId); + + traceScope.TraceSucceeded(schemaId); + return referenceSchema; + } + + private void MapInDiscriminator(ResourceSchemaType resourceSchemaType, bool forRequestSchema, string discriminatorPropertyName, + SchemaRepository schemaRepository) + { + OpenApiSchema referenceSchemaForDerived = schemaRepository.LookupByType(resourceSchemaType.SchemaConstructedType); + + foreach (ResourceType? baseResourceType in GetBaseTypesToMapInto(resourceSchemaType, forRequestSchema)) + { + Type baseSchemaType = baseResourceType == null + ? GetCommonSchemaType(resourceSchemaType.SchemaOpenType)! + : resourceSchemaType.ChangeResourceType(baseResourceType).SchemaConstructedType; + + OpenApiSchema referenceSchemaForBase = schemaRepository.LookupByType(baseSchemaType); + OpenApiSchema inlineSchemaForBase = schemaRepository.Schemas[referenceSchemaForBase.Reference.Id].UnwrapLastExtendedSchema(); + + inlineSchemaForBase.Discriminator ??= new OpenApiDiscriminator + { + PropertyName = discriminatorPropertyName, + Mapping = new SortedDictionary(StringComparer.Ordinal) + }; + + if (RepeatDiscriminatorInResponseDerivedTypes && !forRequestSchema) + { + inlineSchemaForBase.Required.Add(discriminatorPropertyName); + } + + string publicName = resourceSchemaType.ResourceType.PublicName; + + if (inlineSchemaForBase.Discriminator.Mapping.TryAdd(publicName, referenceSchemaForDerived.Reference.ReferenceV3) && baseResourceType == null) + { + MapResourceTypeInEnum(publicName, schemaRepository); + } + } + } + + private static IEnumerable GetBaseTypesToMapInto(ResourceSchemaType resourceSchemaType, bool forRequestSchema) + { + bool dependsOnCommonSchemaType = GetCommonSchemaType(resourceSchemaType.SchemaOpenType) != null; + + if (RepeatDiscriminatorInResponseDerivedTypes && !forRequestSchema) + { + ResourceType? baseType = resourceSchemaType.ResourceType.BaseType; + + while (baseType != null) + { + yield return baseType; + + baseType = baseType.BaseType; + } + } + else + { + if (!dependsOnCommonSchemaType) + { + yield return GetUltimateBaseType(resourceSchemaType.ResourceType); + } + } + + if (dependsOnCommonSchemaType) + { + yield return null; + } + } + + private void MapResourceTypeInEnum(string publicName, SchemaRepository schemaRepository) + { + string schemaId = _schemaIdSelector.GetResourceTypeSchemaId(null); + OpenApiSchema fullSchema = schemaRepository.Schemas[schemaId]; + + if (!fullSchema.Enum.Any(openApiAny => openApiAny is OpenApiString openApiString && openApiString.Value == publicName)) + { + fullSchema.Enum.Add(new OpenApiString(publicName)); + } + } + + private void SetDocumentation(OpenApiSchema fullSchema, ResourceType resourceType) + { + fullSchema.Description = _resourceDocumentationReader.GetDocumentationForType(resourceType); + } + + private void SetLinksVisibility(OpenApiSchema fullSchema, ResourceSchemaType resourceSchemaType, SchemaRepository schemaRepository) + { + _linksVisibilitySchemaGenerator.UpdateSchemaForResource(resourceSchemaType, fullSchema, schemaRepository); + } + + private void GenerateDataSchemasForDirectlyDerivedTypes(ResourceSchemaType resourceSchemaType, bool forRequestSchema, SchemaRepository schemaRepository) + { + OpenApiSchema referenceSchemaForBase = schemaRepository.LookupByType(resourceSchemaType.SchemaConstructedType); + + foreach (ResourceType derivedType in resourceSchemaType.ResourceType.DirectlyDerivedTypes) + { + ResourceSchemaType resourceSchemaTypeForDerived = resourceSchemaType.ChangeResourceType(derivedType); + Type derivedSchemaType = resourceSchemaTypeForDerived.SchemaConstructedType; + + using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, resourceSchemaTypeForDerived.SchemaConstructedType); + + OpenApiSchema referenceSchemaForDerived = _defaultSchemaGenerator.GenerateSchema(derivedSchemaType, schemaRepository); + OpenApiSchema fullSchemaForDerived = schemaRepository.Schemas[referenceSchemaForDerived.Reference.Id]; + fullSchemaForDerived.AdditionalPropertiesAllowed = false; + + OpenApiSchema inlineSchemaForDerived = fullSchemaForDerived.UnwrapLastExtendedSchema(); + SetResourceFields(inlineSchemaForDerived, resourceSchemaTypeForDerived, forRequestSchema, schemaRepository); + + SetAbstract(inlineSchemaForDerived, resourceSchemaTypeForDerived); + RemoveProperties(inlineSchemaForDerived); + MapInDiscriminator(resourceSchemaTypeForDerived, forRequestSchema, JsonApiPropertyName.Type, schemaRepository); + + if (fullSchemaForDerived.AllOf.Count == 0) + { + var compositeSchemaForDerived = new OpenApiSchema + { + AllOf = + [ + referenceSchemaForBase, + fullSchemaForDerived + ], + AdditionalPropertiesAllowed = false + }; + + schemaRepository.Schemas[referenceSchemaForDerived.Reference.Id] = compositeSchemaForDerived; + } + else + { + fullSchemaForDerived.AllOf[0] = referenceSchemaForBase; + } + + if (RequiresRootObjectTypeInDataSchema(resourceSchemaTypeForDerived, forRequestSchema)) + { + OpenApiSchema fullSchemaForData = schemaRepository.Schemas[referenceSchemaForDerived.Reference.Id]; + fullSchemaForData.Extensions[SetSchemaTypeToObjectDocumentFilter.RequiresRootObjectTypeKey] = new OpenApiBoolean(true); + } + + GenerateDataSchemasForDirectlyDerivedTypes(resourceSchemaTypeForDerived, forRequestSchema, schemaRepository); + + traceScope.TraceSucceeded(referenceSchemaForDerived.Reference.Id); + } + } + + private static void RemoveProperties(OpenApiSchema fullSchema) + { + foreach (string propertyName in fullSchema.Properties.Keys) + { + fullSchema.Properties.Remove(propertyName); + fullSchema.Required.Remove(propertyName); + } + } + + private static bool RequiresRootObjectTypeInDataSchema(ResourceSchemaType resourceSchemaType, bool forRequestSchema) + { + Type? commonDataSchemaType = GetCommonSchemaType(resourceSchemaType.SchemaOpenType); + + if (forRequestSchema && (commonDataSchemaType == typeof(IdentifierInRequest) || + (!resourceSchemaType.ResourceType.ClrType.IsAbstract && commonDataSchemaType is { IsGenericType: false }))) + { + // Bug workaround for NSwag, which fails to properly infer implicit { "type": "object" } of outer schema when it appears inside an allOf. + // As a result, the required Data property in the generated client is assigned "default!" instead of a new instance. + // But there's another bug on top of that: When the declared type of Data is abstract, it still generates assignment with a new instance, which fails to compile. + return true; + } + + return false; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/LinksVisibilitySchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/LinksVisibilitySchemaGenerator.cs new file mode 100644 index 0000000000..5c099a3fc1 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/LinksVisibilitySchemaGenerator.cs @@ -0,0 +1,208 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Relationships; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; +using JsonApiDotNetCore.Resources.Annotations; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; + +/// +/// Hides links that are never returned. +/// +/// +/// Tradeoff: Special-casing links per resource type and per relationship means an explosion of expanded types, only because the links visibility may +/// vary. Furthermore, relationship links fallback to their left-type resource, whereas we generate right-type component schemas for relationships. To +/// keep it simple, we take the union of exposed links on resource types and relationships. Only what's not in this unification gets hidden. For example, +/// when options == None, typeof(Blogs) == Self, and typeof(Posts) == Related, we'll keep Self | Related for both Blogs and Posts, and remove any other +/// links. +/// +internal sealed class LinksVisibilitySchemaGenerator +{ + private const LinkTypes ResourceTopLinkTypes = LinkTypes.Self | LinkTypes.DescribedBy; + private const LinkTypes ResourceCollectionTopLinkTypes = LinkTypes.Self | LinkTypes.DescribedBy | LinkTypes.Pagination; + private const LinkTypes ResourceIdentifierTopLinkTypes = LinkTypes.Self | LinkTypes.Related | LinkTypes.DescribedBy; + private const LinkTypes ResourceIdentifierCollectionTopLinkTypes = LinkTypes.Self | LinkTypes.Related | LinkTypes.DescribedBy | LinkTypes.Pagination; + private const LinkTypes ErrorTopLinkTypes = LinkTypes.Self | LinkTypes.DescribedBy; + private const LinkTypes RelationshipLinkTypes = LinkTypes.Self | LinkTypes.Related; + private const LinkTypes ResourceLinkTypes = LinkTypes.Self; + + private static readonly Dictionary LinksInJsonApiSchemaTypes = new() + { + [typeof(NullableSecondaryResponseDocument<>)] = ResourceTopLinkTypes, + [typeof(PrimaryResponseDocument<>)] = ResourceTopLinkTypes, + [typeof(SecondaryResponseDocument<>)] = ResourceTopLinkTypes, + [typeof(CollectionResponseDocument<>)] = ResourceCollectionTopLinkTypes, + [typeof(IdentifierResponseDocument<>)] = ResourceIdentifierTopLinkTypes, + [typeof(NullableIdentifierResponseDocument<>)] = ResourceIdentifierTopLinkTypes, + [typeof(IdentifierCollectionResponseDocument<>)] = ResourceIdentifierCollectionTopLinkTypes, + [typeof(ErrorResponseDocument)] = ErrorTopLinkTypes, + [typeof(OperationsResponseDocument)] = ResourceTopLinkTypes, + [typeof(NullableToOneInResponse<>)] = RelationshipLinkTypes, + [typeof(ToManyInResponse<>)] = RelationshipLinkTypes, + [typeof(ToOneInResponse<>)] = RelationshipLinkTypes, + [typeof(DataInResponse<>)] = ResourceLinkTypes + }; + + private static readonly Dictionary> LinkTypeToPropertyNamesMap = new() + { + [LinkTypes.Self] = ["self"], + [LinkTypes.Related] = ["related"], + [LinkTypes.DescribedBy] = ["describedby"], + [LinkTypes.Pagination] = + [ + "first", + "last", + "prev", + "next" + ] + }; + + private readonly Lazy _lazyLinksVisibility; + + public LinksVisibilitySchemaGenerator(IJsonApiOptions options, IResourceGraph resourceGraph) + { + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(resourceGraph); + + _lazyLinksVisibility = new Lazy(() => new LinksVisibility(options, resourceGraph), LazyThreadSafetyMode.ExecutionAndPublication); + } + + public void UpdateSchemaForTopLevel(Type schemaType, OpenApiSchema fullSchemaForLinksContainer, SchemaRepository schemaRepository) + { + ArgumentNullException.ThrowIfNull(schemaType); + ArgumentNullException.ThrowIfNull(fullSchemaForLinksContainer); + + Type lookupType = schemaType.ConstructedToOpenType(); + + if (LinksInJsonApiSchemaTypes.TryGetValue(lookupType, out LinkTypes possibleLinkTypes)) + { + UpdateLinksProperty(fullSchemaForLinksContainer, _lazyLinksVisibility.Value.TopLevelLinks, possibleLinkTypes, schemaRepository); + } + } + + public void UpdateSchemaForResource(ResourceSchemaType resourceSchemaType, OpenApiSchema fullSchemaForResourceData, SchemaRepository schemaRepository) + { + ArgumentNullException.ThrowIfNull(resourceSchemaType); + ArgumentNullException.ThrowIfNull(fullSchemaForResourceData); + + if (LinksInJsonApiSchemaTypes.TryGetValue(resourceSchemaType.SchemaOpenType, out LinkTypes possibleLinkTypes)) + { + UpdateLinksProperty(fullSchemaForResourceData, _lazyLinksVisibility.Value.ResourceLinks, possibleLinkTypes, schemaRepository); + } + } + + public void UpdateSchemaForRelationship(Type schemaType, OpenApiSchema fullSchemaForRelationship, SchemaRepository schemaRepository) + { + ArgumentNullException.ThrowIfNull(schemaType); + ArgumentNullException.ThrowIfNull(fullSchemaForRelationship); + + Type lookupType = schemaType.ConstructedToOpenType(); + + if (LinksInJsonApiSchemaTypes.TryGetValue(lookupType, out LinkTypes possibleLinkTypes)) + { + UpdateLinksProperty(fullSchemaForRelationship, _lazyLinksVisibility.Value.RelationshipLinks, possibleLinkTypes, schemaRepository); + } + } + + private void UpdateLinksProperty(OpenApiSchema fullSchemaForLinksContainer, LinkTypes visibleLinkTypes, LinkTypes possibleLinkTypes, + SchemaRepository schemaRepository) + { + OpenApiSchema referenceSchemaForLinks = fullSchemaForLinksContainer.Properties[JsonApiPropertyName.Links].UnwrapLastExtendedSchema(); + + if ((visibleLinkTypes & possibleLinkTypes) == 0) + { + fullSchemaForLinksContainer.Required.Remove(JsonApiPropertyName.Links); + fullSchemaForLinksContainer.Properties.Remove(JsonApiPropertyName.Links); + + schemaRepository.Schemas.Remove(referenceSchemaForLinks.Reference.Id); + } + else if (visibleLinkTypes != possibleLinkTypes) + { + string linksSchemaId = referenceSchemaForLinks.Reference.Id; + + if (schemaRepository.Schemas.TryGetValue(linksSchemaId, out OpenApiSchema? fullSchemaForLinks)) + { + UpdateLinkProperties(fullSchemaForLinks, visibleLinkTypes); + } + } + } + + private void UpdateLinkProperties(OpenApiSchema fullSchemaForLinks, LinkTypes availableLinkTypes) + { + foreach (string propertyName in LinkTypeToPropertyNamesMap.Where(pair => !availableLinkTypes.HasFlag(pair.Key)).SelectMany(pair => pair.Value)) + { + fullSchemaForLinks.Required.Remove(propertyName); + fullSchemaForLinks.Properties.Remove(propertyName); + } + } + + private sealed class LinksVisibility + { + public LinkTypes TopLevelLinks { get; } + public LinkTypes ResourceLinks { get; } + public LinkTypes RelationshipLinks { get; } + + public LinksVisibility(IJsonApiOptions options, IResourceGraph resourceGraph) + { + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(resourceGraph); + + var unionTopLevelLinks = LinkTypes.None; + var unionResourceLinks = LinkTypes.None; + var unionRelationshipLinks = LinkTypes.None; + + foreach (ResourceType resourceType in resourceGraph.GetResourceTypes()) + { + LinkTypes topLevelLinks = GetTopLevelLinks(resourceType, options); + unionTopLevelLinks |= topLevelLinks; + + LinkTypes resourceLinks = GetResourceLinks(resourceType, options); + unionResourceLinks |= resourceLinks; + + LinkTypes relationshipLinks = GetRelationshipLinks(resourceType, options); + unionRelationshipLinks |= relationshipLinks; + } + + TopLevelLinks = Normalize(unionTopLevelLinks); + ResourceLinks = Normalize(unionResourceLinks); + RelationshipLinks = Normalize(unionRelationshipLinks); + } + + private LinkTypes GetTopLevelLinks(ResourceType resourceType, IJsonApiOptions options) + { + return resourceType.TopLevelLinks != LinkTypes.NotConfigured ? resourceType.TopLevelLinks : + options.TopLevelLinks == LinkTypes.NotConfigured ? LinkTypes.None : options.TopLevelLinks; + } + + private LinkTypes GetResourceLinks(ResourceType resourceType, IJsonApiOptions options) + { + return resourceType.ResourceLinks != LinkTypes.NotConfigured ? resourceType.ResourceLinks : + options.ResourceLinks == LinkTypes.NotConfigured ? LinkTypes.None : options.ResourceLinks; + } + + private LinkTypes GetRelationshipLinks(ResourceType resourceType, IJsonApiOptions options) + { + LinkTypes unionRelationshipLinks = resourceType.RelationshipLinks != LinkTypes.NotConfigured ? resourceType.RelationshipLinks : + options.RelationshipLinks == LinkTypes.NotConfigured ? LinkTypes.None : options.RelationshipLinks; + + foreach (RelationshipAttribute relationship in resourceType.Relationships) + { + LinkTypes relationshipLinks = relationship.Links != LinkTypes.NotConfigured ? relationship.Links : + relationship.LeftType.RelationshipLinks != LinkTypes.NotConfigured ? relationship.LeftType.RelationshipLinks : + options.RelationshipLinks == LinkTypes.NotConfigured ? LinkTypes.None : options.RelationshipLinks; + + unionRelationshipLinks |= relationshipLinks; + } + + return unionRelationshipLinks; + } + + private static LinkTypes Normalize(LinkTypes linkTypes) + { + return linkTypes != LinkTypes.None ? linkTypes & ~LinkTypes.None : linkTypes; + } + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/MetaSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/MetaSchemaGenerator.cs new file mode 100644 index 0000000000..1e1bd07852 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/MetaSchemaGenerator.cs @@ -0,0 +1,50 @@ +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; + +internal sealed class MetaSchemaGenerator +{ + private static readonly Type SchemaType = typeof(Meta); + private readonly SchemaGenerationTracer _schemaGenerationTracer; + private readonly JsonApiSchemaIdSelector _schemaIdSelector; + + public MetaSchemaGenerator(SchemaGenerationTracer schemaGenerationTracer, JsonApiSchemaIdSelector schemaIdSelector) + { + ArgumentNullException.ThrowIfNull(schemaGenerationTracer); + ArgumentNullException.ThrowIfNull(schemaIdSelector); + + _schemaGenerationTracer = schemaGenerationTracer; + _schemaIdSelector = schemaIdSelector; + } + + public OpenApiSchema GenerateSchema(SchemaRepository schemaRepository) + { + ArgumentNullException.ThrowIfNull(schemaRepository); + + if (schemaRepository.TryLookupByType(SchemaType, out OpenApiSchema? referenceSchema)) + { + return referenceSchema; + } + + using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, SchemaType); + + var fullSchema = new OpenApiSchema + { + Type = "object", + AdditionalProperties = new OpenApiSchema + { + Nullable = true + } + }; + + string schemaId = _schemaIdSelector.GetMetaSchemaId(); + + referenceSchema = schemaRepository.AddDefinition(schemaId, fullSchema); + schemaRepository.RegisterType(SchemaType, schemaId); + + traceScope.TraceSucceeded(schemaId); + return referenceSchema; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/RelationshipIdentifierSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/RelationshipIdentifierSchemaGenerator.cs new file mode 100644 index 0000000000..98f176e8df --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/RelationshipIdentifierSchemaGenerator.cs @@ -0,0 +1,94 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources.Annotations; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; + +internal sealed class RelationshipIdentifierSchemaGenerator +{ + private readonly SchemaGenerationTracer _schemaGenerationTracer; + private readonly SchemaGenerator _defaultSchemaGenerator; + private readonly ResourceTypeSchemaGenerator _resourceTypeSchemaGenerator; + private readonly ResourceIdSchemaGenerator _resourceIdSchemaGenerator; + private readonly RelationshipNameSchemaGenerator _relationshipNameSchemaGenerator; + private readonly JsonApiSchemaIdSelector _schemaIdSelector; + + public RelationshipIdentifierSchemaGenerator(SchemaGenerationTracer schemaGenerationTracer, SchemaGenerator defaultSchemaGenerator, + ResourceTypeSchemaGenerator resourceTypeSchemaGenerator, ResourceIdSchemaGenerator resourceIdSchemaGenerator, + RelationshipNameSchemaGenerator relationshipNameSchemaGenerator, JsonApiSchemaIdSelector schemaIdSelector) + { + ArgumentNullException.ThrowIfNull(schemaGenerationTracer); + ArgumentNullException.ThrowIfNull(defaultSchemaGenerator); + ArgumentNullException.ThrowIfNull(resourceTypeSchemaGenerator); + ArgumentNullException.ThrowIfNull(resourceIdSchemaGenerator); + ArgumentNullException.ThrowIfNull(relationshipNameSchemaGenerator); + ArgumentNullException.ThrowIfNull(schemaIdSelector); + + _schemaGenerationTracer = schemaGenerationTracer; + _defaultSchemaGenerator = defaultSchemaGenerator; + _resourceTypeSchemaGenerator = resourceTypeSchemaGenerator; + _resourceIdSchemaGenerator = resourceIdSchemaGenerator; + _relationshipNameSchemaGenerator = relationshipNameSchemaGenerator; + _schemaIdSelector = schemaIdSelector; + } + + public OpenApiSchema GenerateSchema(RelationshipAttribute relationship, SchemaRepository schemaRepository) + { + ArgumentNullException.ThrowIfNull(relationship); + ArgumentNullException.ThrowIfNull(schemaRepository); + + string schemaId = _schemaIdSelector.GetRelationshipIdentifierSchemaId(relationship); + + if (schemaRepository.Schemas.ContainsKey(schemaId)) + { + return new OpenApiSchema + { + Reference = new OpenApiReference + { + Id = schemaId, + Type = ReferenceType.Schema + } + }; + } + + using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, relationship); + + Type relationshipIdentifierConstructedType = typeof(RelationshipIdentifier<>).MakeGenericType(relationship.LeftType.ClrType); + ConsistencyGuard.ThrowIf(schemaRepository.TryLookupByType(relationshipIdentifierConstructedType, out _)); + + OpenApiSchema referenceSchemaForIdentifier = _defaultSchemaGenerator.GenerateSchema(relationshipIdentifierConstructedType, schemaRepository); + OpenApiSchema fullSchemaForIdentifier = schemaRepository.Schemas[referenceSchemaForIdentifier.Reference.Id]; + + fullSchemaForIdentifier.Properties.Remove(JsonApiPropertyName.Meta); + + SetResourceType(fullSchemaForIdentifier, relationship.LeftType, schemaRepository); + SetResourceId(fullSchemaForIdentifier, relationship.LeftType, schemaRepository); + SetRelationship(fullSchemaForIdentifier, relationship, schemaRepository); + + schemaRepository.ReplaceSchemaId(relationshipIdentifierConstructedType, schemaId); + referenceSchemaForIdentifier.Reference.Id = schemaId; + + traceScope.TraceSucceeded(schemaId); + return referenceSchemaForIdentifier; + } + + private void SetResourceType(OpenApiSchema fullSchemaForIdentifier, ResourceType resourceType, SchemaRepository schemaRepository) + { + OpenApiSchema referenceSchema = _resourceTypeSchemaGenerator.GenerateSchema(resourceType, schemaRepository); + fullSchemaForIdentifier.Properties[JsonApiPropertyName.Type] = referenceSchema.WrapInExtendedSchema(); + } + + private void SetResourceId(OpenApiSchema fullSchemaForResourceData, ResourceType resourceType, SchemaRepository schemaRepository) + { + OpenApiSchema idSchema = _resourceIdSchemaGenerator.GenerateSchema(resourceType, schemaRepository); + fullSchemaForResourceData.Properties[JsonApiPropertyName.Id] = idSchema; + } + + private void SetRelationship(OpenApiSchema fullSchemaForIdentifier, RelationshipAttribute relationship, SchemaRepository schemaRepository) + { + OpenApiSchema referenceSchema = _relationshipNameSchemaGenerator.GenerateSchema(relationship, schemaRepository); + fullSchemaForIdentifier.Properties[JsonApiPropertyName.Relationship] = referenceSchema.WrapInExtendedSchema(); + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/RelationshipNameSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/RelationshipNameSchemaGenerator.cs new file mode 100644 index 0000000000..7f5c0c5d3a --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/RelationshipNameSchemaGenerator.cs @@ -0,0 +1,54 @@ +using JsonApiDotNetCore.Resources.Annotations; +using Microsoft.OpenApi.Any; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; + +internal sealed class RelationshipNameSchemaGenerator +{ + private readonly SchemaGenerationTracer _schemaGenerationTracer; + private readonly JsonApiSchemaIdSelector _schemaIdSelector; + + public RelationshipNameSchemaGenerator(SchemaGenerationTracer schemaGenerationTracer, JsonApiSchemaIdSelector schemaIdSelector) + { + ArgumentNullException.ThrowIfNull(schemaGenerationTracer); + ArgumentNullException.ThrowIfNull(schemaIdSelector); + + _schemaGenerationTracer = schemaGenerationTracer; + _schemaIdSelector = schemaIdSelector; + } + + public OpenApiSchema GenerateSchema(RelationshipAttribute relationship, SchemaRepository schemaRepository) + { + ArgumentNullException.ThrowIfNull(relationship); + ArgumentNullException.ThrowIfNull(schemaRepository); + + string schemaId = _schemaIdSelector.GetRelationshipNameSchemaId(relationship); + + if (schemaRepository.Schemas.ContainsKey(schemaId)) + { + return new OpenApiSchema + { + Reference = new OpenApiReference + { + Id = schemaId, + Type = ReferenceType.Schema + } + }; + } + + using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, relationship); + + var fullSchema = new OpenApiSchema + { + Type = "string", + Enum = [new OpenApiString(relationship.PublicName)] + }; + + OpenApiSchema referenceSchema = schemaRepository.AddDefinition(schemaId, fullSchema); + + traceScope.TraceSucceeded(schemaId); + return referenceSchema; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/ResourceIdSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/ResourceIdSchemaGenerator.cs new file mode 100644 index 0000000000..21bc5020ed --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/ResourceIdSchemaGenerator.cs @@ -0,0 +1,45 @@ +using JsonApiDotNetCore.Configuration; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; + +internal sealed class ResourceIdSchemaGenerator +{ + private readonly SchemaGenerator _defaultSchemaGenerator; + + public ResourceIdSchemaGenerator(SchemaGenerator defaultSchemaGenerator) + { + ArgumentNullException.ThrowIfNull(defaultSchemaGenerator); + + _defaultSchemaGenerator = defaultSchemaGenerator; + } + + public OpenApiSchema GenerateSchema(ResourceType resourceType, SchemaRepository schemaRepository) + { + ArgumentNullException.ThrowIfNull(resourceType); + + return GenerateSchema(resourceType.IdentityClrType, schemaRepository); + } + + public OpenApiSchema GenerateSchema(Type resourceIdClrType, SchemaRepository schemaRepository) + { + ArgumentNullException.ThrowIfNull(resourceIdClrType); + ArgumentNullException.ThrowIfNull(schemaRepository); + + OpenApiSchema idSchema = _defaultSchemaGenerator.GenerateSchema(resourceIdClrType, schemaRepository); + ConsistencyGuard.ThrowIf(idSchema.Reference != null); + + idSchema.Type = "string"; + + if (resourceIdClrType != typeof(string)) + { + // When using string IDs, it's discouraged (but possible) to use an empty string as primary key value, because + // some things won't work: get-by-id, update and delete resource are impossible, and rendered links are unusable. + // For other ID types, provide the length constraint as a fallback in case the type hint isn't recognized. + idSchema.MinLength = 1; + } + + return idSchema; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/ResourceTypeSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/ResourceTypeSchemaGenerator.cs new file mode 100644 index 0000000000..eb933bedbe --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/ResourceTypeSchemaGenerator.cs @@ -0,0 +1,91 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; +using Microsoft.OpenApi.Any; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; + +internal sealed class ResourceTypeSchemaGenerator +{ + private readonly SchemaGenerationTracer _schemaGenerationTracer; + private readonly JsonApiSchemaIdSelector _schemaIdSelector; + + public ResourceTypeSchemaGenerator(SchemaGenerationTracer schemaGenerationTracer, JsonApiSchemaIdSelector schemaIdSelector) + { + ArgumentNullException.ThrowIfNull(schemaGenerationTracer); + ArgumentNullException.ThrowIfNull(schemaIdSelector); + + _schemaGenerationTracer = schemaGenerationTracer; + _schemaIdSelector = schemaIdSelector; + } + + public OpenApiSchema GenerateSchema(ResourceType resourceType, SchemaRepository schemaRepository) + { + ArgumentNullException.ThrowIfNull(resourceType); + ArgumentNullException.ThrowIfNull(schemaRepository); + + if (schemaRepository.TryLookupByType(resourceType.ClrType, out OpenApiSchema? referenceSchema)) + { + return referenceSchema; + } + + using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, resourceType.ClrType); + + var fullSchema = new OpenApiSchema + { + Type = "string", + Enum = resourceType.ClrType.IsAbstract ? [] : [new OpenApiString(resourceType.PublicName)], + Extensions = + { + [StringEnumOrderingFilter.RequiresSortKey] = new OpenApiBoolean(true) + } + }; + + foreach (ResourceType derivedType in resourceType.GetAllConcreteDerivedTypes()) + { + fullSchema.Enum.Add(new OpenApiString(derivedType.PublicName)); + } + + string schemaId = _schemaIdSelector.GetResourceTypeSchemaId(resourceType); + + referenceSchema = schemaRepository.AddDefinition(schemaId, fullSchema); + schemaRepository.RegisterType(resourceType.ClrType, schemaId); + + traceScope.TraceSucceeded(schemaId); + return referenceSchema; + } + + public OpenApiSchema GenerateSchema(SchemaRepository schemaRepository) + { + string schemaId = _schemaIdSelector.GetResourceTypeSchemaId(null); + + if (schemaRepository.Schemas.ContainsKey(schemaId)) + { + return new OpenApiSchema + { + Reference = new OpenApiReference + { + Id = schemaId, + Type = ReferenceType.Schema + } + }; + } + + using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this); + + var fullSchema = new OpenApiSchema + { + Type = "string", + Extensions = + { + [StringEnumOrderingFilter.RequiresSortKey] = new OpenApiBoolean(true) + } + }; + + OpenApiSchema referenceSchema = schemaRepository.AddDefinition(schemaId, fullSchema); + + traceScope.TraceSucceeded(schemaId); + return referenceSchema; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/AtomicOperationsDocumentSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/AtomicOperationsDocumentSchemaGenerator.cs new file mode 100644 index 0000000000..f128f89299 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/AtomicOperationsDocumentSchemaGenerator.cs @@ -0,0 +1,485 @@ +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.AtomicOperations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; +using JsonApiDotNetCore.Resources.Annotations; +using JsonApiDotNetCore.Serialization.Objects; +using Microsoft.OpenApi.Any; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Documents; + +/// +/// Generates the OpenAPI component schema for an atomic:operations request/response document. +/// +internal sealed class AtomicOperationsDocumentSchemaGenerator : DocumentSchemaGenerator +{ + private static readonly Type AtomicOperationAbstractType = typeof(AtomicOperation); + + private readonly SchemaGenerationTracer _schemaGenerationTracer; + private readonly SchemaGenerator _defaultSchemaGenerator; + private readonly AtomicOperationCodeSchemaGenerator _atomicOperationCodeSchemaGenerator; + private readonly DataSchemaGenerator _dataSchemaGenerator; + private readonly RelationshipIdentifierSchemaGenerator _relationshipIdentifierSchemaGenerator; + private readonly DataContainerSchemaGenerator _dataContainerSchemaGenerator; + private readonly MetaSchemaGenerator _metaSchemaGenerator; + private readonly IAtomicOperationFilter _atomicOperationFilter; + private readonly JsonApiSchemaIdSelector _schemaIdSelector; + private readonly ResourceFieldValidationMetadataProvider _resourceFieldValidationMetadataProvider; + private readonly IResourceGraph _resourceGraph; + + public AtomicOperationsDocumentSchemaGenerator(SchemaGenerationTracer schemaGenerationTracer, SchemaGenerator defaultSchemaGenerator, + AtomicOperationCodeSchemaGenerator atomicOperationCodeSchemaGenerator, DataSchemaGenerator dataSchemaGenerator, + RelationshipIdentifierSchemaGenerator relationshipIdentifierSchemaGenerator, DataContainerSchemaGenerator dataContainerSchemaGenerator, + MetaSchemaGenerator metaSchemaGenerator, LinksVisibilitySchemaGenerator linksVisibilitySchemaGenerator, IAtomicOperationFilter atomicOperationFilter, + JsonApiSchemaIdSelector schemaIdSelector, ResourceFieldValidationMetadataProvider resourceFieldValidationMetadataProvider, IJsonApiOptions options, + IResourceGraph resourceGraph) + : base(schemaGenerationTracer, metaSchemaGenerator, linksVisibilitySchemaGenerator, options) + { + ArgumentNullException.ThrowIfNull(defaultSchemaGenerator); + ArgumentNullException.ThrowIfNull(atomicOperationCodeSchemaGenerator); + ArgumentNullException.ThrowIfNull(dataSchemaGenerator); + ArgumentNullException.ThrowIfNull(relationshipIdentifierSchemaGenerator); + ArgumentNullException.ThrowIfNull(dataContainerSchemaGenerator); + ArgumentNullException.ThrowIfNull(atomicOperationFilter); + ArgumentNullException.ThrowIfNull(schemaIdSelector); + ArgumentNullException.ThrowIfNull(resourceFieldValidationMetadataProvider); + ArgumentNullException.ThrowIfNull(resourceGraph); + + _schemaGenerationTracer = schemaGenerationTracer; + _defaultSchemaGenerator = defaultSchemaGenerator; + _atomicOperationCodeSchemaGenerator = atomicOperationCodeSchemaGenerator; + _dataSchemaGenerator = dataSchemaGenerator; + _relationshipIdentifierSchemaGenerator = relationshipIdentifierSchemaGenerator; + _dataContainerSchemaGenerator = dataContainerSchemaGenerator; + _metaSchemaGenerator = metaSchemaGenerator; + _atomicOperationFilter = atomicOperationFilter; + _schemaIdSelector = schemaIdSelector; + _resourceFieldValidationMetadataProvider = resourceFieldValidationMetadataProvider; + _resourceGraph = resourceGraph; + } + + public override bool CanGenerate(Type schemaType) + { + return schemaType == typeof(OperationsRequestDocument) || schemaType == typeof(OperationsResponseDocument); + } + + protected override OpenApiSchema GenerateDocumentSchema(Type schemaType, SchemaRepository schemaRepository) + { + ArgumentNullException.ThrowIfNull(schemaType); + ArgumentNullException.ThrowIfNull(schemaRepository); + + bool isRequestSchema = schemaType == typeof(OperationsRequestDocument); + + if (isRequestSchema) + { + GenerateSchemasForRequestDocument(schemaRepository); + } + else + { + GenerateSchemasForResponseDocument(schemaRepository); + } + + return _defaultSchemaGenerator.GenerateSchema(schemaType, schemaRepository); + } + + private void GenerateSchemasForRequestDocument(SchemaRepository schemaRepository) + { + _ = GenerateSchemaForAbstractOperation(schemaRepository); + + foreach (ResourceType resourceType in _resourceGraph.GetResourceTypes().Where(resourceType => resourceType.BaseType == null)) + { + GenerateSchemaForOperation(resourceType, schemaRepository); + } + } + + private OpenApiSchema GenerateSchemaForAbstractOperation(SchemaRepository schemaRepository) + { + if (schemaRepository.TryLookupByType(AtomicOperationAbstractType, out OpenApiSchema? referenceSchema)) + { + return referenceSchema; + } + + using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, AtomicOperationAbstractType); + + OpenApiSchema referenceSchemaForMeta = _metaSchemaGenerator.GenerateSchema(schemaRepository); + + var fullSchema = new OpenApiSchema + { + Type = "object", + Required = new SortedSet([OpenApiMediaTypeExtension.FullyQualifiedOpenApiDiscriminatorPropertyName]), + Properties = new Dictionary + { + [OpenApiMediaTypeExtension.FullyQualifiedOpenApiDiscriminatorPropertyName] = new() + { + Type = "string" + }, + [referenceSchemaForMeta.Reference.Id] = referenceSchemaForMeta.WrapInExtendedSchema() + }, + AdditionalPropertiesAllowed = false, + Discriminator = new OpenApiDiscriminator + { + PropertyName = OpenApiMediaTypeExtension.FullyQualifiedOpenApiDiscriminatorPropertyName, + Mapping = new SortedDictionary(StringComparer.Ordinal) + }, + Extensions = + { + ["x-abstract"] = new OpenApiBoolean(true) + } + }; + + string schemaId = _schemaIdSelector.GetSchemaId(AtomicOperationAbstractType); + + referenceSchema = schemaRepository.AddDefinition(schemaId, fullSchema); + schemaRepository.RegisterType(AtomicOperationAbstractType, schemaId); + + traceScope.TraceSucceeded(schemaId); + return referenceSchema; + } + + private void GenerateSchemaForOperation(ResourceType resourceType, SchemaRepository schemaRepository) + { + GenerateSchemaForResourceOperation(typeof(CreateOperation<>), resourceType, AtomicOperationCode.Add, schemaRepository); + GenerateSchemaForResourceOperation(typeof(UpdateOperation<>), resourceType, AtomicOperationCode.Update, schemaRepository); + GenerateSchemaForResourceOperation(typeof(DeleteOperation<>), resourceType, AtomicOperationCode.Remove, schemaRepository); + + foreach (RelationshipAttribute relationship in GetRelationshipsInTypeHierarchy(resourceType)) + { + if (relationship is HasOneAttribute) + { + GenerateSchemaForRelationshipOperation(typeof(UpdateToOneRelationshipOperation<>), relationship, AtomicOperationCode.Update, schemaRepository); + } + else + { + GenerateSchemaForRelationshipOperation(typeof(AddToRelationshipOperation<>), relationship, AtomicOperationCode.Add, schemaRepository); + GenerateSchemaForRelationshipOperation(typeof(UpdateToManyRelationshipOperation<>), relationship, AtomicOperationCode.Update, schemaRepository); + GenerateSchemaForRelationshipOperation(typeof(RemoveFromRelationshipOperation<>), relationship, AtomicOperationCode.Remove, schemaRepository); + } + } + } + + private void GenerateSchemaForResourceOperation(Type operationOpenType, ResourceType resourceType, AtomicOperationCode operationCode, + SchemaRepository schemaRepository) + { + WriteOperationKind writeOperation = GetKindOfResourceOperation(operationCode); + + if (IsResourceTypeEnabled(resourceType, writeOperation)) + { + Type operationConstructedType = ChangeResourceTypeInSchemaType(operationOpenType, resourceType); + + using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, operationConstructedType); + + bool needsEmptyDerivedSchema = resourceType.BaseType != null && _atomicOperationFilter.IsEnabled(resourceType.BaseType, writeOperation); + + if (!needsEmptyDerivedSchema) + { + Type identifierSchemaType = typeof(IdentifierInRequest<>).MakeGenericType(resourceType.ClrType); + _ = _dataSchemaGenerator.GenerateSchema(identifierSchemaType, true, schemaRepository); + + bool hasDataProperty = operationOpenType != typeof(DeleteOperation<>); + + if (hasDataProperty) + { + _ = _dataContainerSchemaGenerator.GenerateSchema(operationConstructedType, resourceType, true, false, schemaRepository); + } + } + + OpenApiSchema referenceSchemaForOperation = _defaultSchemaGenerator.GenerateSchema(operationConstructedType, schemaRepository); + OpenApiSchema fullSchemaForOperation = schemaRepository.Schemas[referenceSchemaForOperation.Reference.Id]; + fullSchemaForOperation.AdditionalPropertiesAllowed = false; + OpenApiSchema inlineSchemaForOperation = fullSchemaForOperation.UnwrapLastExtendedSchema(); + + if (needsEmptyDerivedSchema) + { + Type baseOperationSchemaType = ChangeResourceTypeInSchemaType(operationOpenType, resourceType.BaseType!); + OpenApiSchema referenceSchemaForBaseOperation = schemaRepository.LookupByType(baseOperationSchemaType); + + RemoveProperties(inlineSchemaForOperation); + fullSchemaForOperation.AllOf[0] = referenceSchemaForBaseOperation; + } + else + { + SetOperationCode(inlineSchemaForOperation, operationCode, schemaRepository); + } + + string discriminatorValue = _schemaIdSelector.GetAtomicOperationDiscriminatorValue(operationCode, resourceType); + MapInDiscriminator(referenceSchemaForOperation, discriminatorValue, schemaRepository); + + traceScope.TraceSucceeded(referenceSchemaForOperation.Reference.Id); + } + + foreach (ResourceType derivedType in resourceType.DirectlyDerivedTypes) + { + GenerateSchemaForResourceOperation(operationOpenType, derivedType, operationCode, schemaRepository); + } + } + + private static WriteOperationKind GetKindOfResourceOperation(AtomicOperationCode operationCode) + { + WriteOperationKind? writeOperation = null; + + if (operationCode == AtomicOperationCode.Add) + { + writeOperation = WriteOperationKind.CreateResource; + } + else if (operationCode == AtomicOperationCode.Update) + { + writeOperation = WriteOperationKind.UpdateResource; + } + else if (operationCode == AtomicOperationCode.Remove) + { + writeOperation = WriteOperationKind.DeleteResource; + } + + ConsistencyGuard.ThrowIf(writeOperation == null); + return writeOperation.Value; + } + + private bool IsResourceTypeEnabled(ResourceType resourceType, WriteOperationKind writeOperation) + { + return _atomicOperationFilter.IsEnabled(resourceType, writeOperation); + } + + private static Type ChangeResourceTypeInSchemaType(Type schemaOpenType, ResourceType resourceType) + { + return schemaOpenType.MakeGenericType(resourceType.ClrType); + } + + private static void RemoveProperties(OpenApiSchema fullSchema) + { + foreach (string propertyName in fullSchema.Properties.Keys) + { + fullSchema.Properties.Remove(propertyName); + fullSchema.Required.Remove(propertyName); + } + } + + private void SetOperationCode(OpenApiSchema fullSchema, AtomicOperationCode operationCode, SchemaRepository schemaRepository) + { + OpenApiSchema referenceSchema = _atomicOperationCodeSchemaGenerator.GenerateSchema(operationCode, schemaRepository); + fullSchema.Properties[JsonApiPropertyName.Op] = referenceSchema.WrapInExtendedSchema(); + } + + private static void MapInDiscriminator(OpenApiSchema referenceSchemaForOperation, string discriminatorValue, SchemaRepository schemaRepository) + { + OpenApiSchema referenceSchemaForAbstractOperation = schemaRepository.LookupByType(AtomicOperationAbstractType); + OpenApiSchema fullSchemaForAbstractOperation = schemaRepository.Schemas[referenceSchemaForAbstractOperation.Reference.Id]; + fullSchemaForAbstractOperation.Discriminator.Mapping.Add(discriminatorValue, referenceSchemaForOperation.Reference.ReferenceV3); + } + + private static HashSet GetRelationshipsInTypeHierarchy(ResourceType baseType) + { + HashSet relationships = baseType.Relationships.ToHashSet(); + + if (baseType.IsPartOfTypeHierarchy()) + { + IncludeRelationshipsInDirectlyDerivedTypes(baseType, relationships); + } + + return relationships; + } + + private static void IncludeRelationshipsInDirectlyDerivedTypes(ResourceType baseType, HashSet relationships) + { + foreach (ResourceType derivedType in baseType.DirectlyDerivedTypes) + { + IncludeRelationshipsInDerivedType(derivedType, relationships); + } + } + + private static void IncludeRelationshipsInDerivedType(ResourceType derivedType, HashSet relationships) + { + foreach (RelationshipAttribute relationshipInDerivedType in derivedType.Relationships) + { + relationships.Add(relationshipInDerivedType); + } + + IncludeRelationshipsInDirectlyDerivedTypes(derivedType, relationships); + } + + private void GenerateSchemaForRelationshipOperation(Type operationOpenType, RelationshipAttribute relationship, AtomicOperationCode operationCode, + SchemaRepository schemaRepository) + { + WriteOperationKind writeOperation = GetKindOfRelationshipOperation(operationCode); + + if (!IsRelationshipEnabled(relationship, writeOperation)) + { + return; + } + + using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, operationOpenType, relationship); + + RelationshipAttribute? relationshipInAnyBaseResourceType = GetRelationshipEnabledInAnyBase(relationship, writeOperation); + + OpenApiSchema? referenceSchemaForRelationshipIdentifier; + + if (relationshipInAnyBaseResourceType == null) + { + Type rightSchemaType = typeof(IdentifierInRequest<>).MakeGenericType(relationship.RightType.ClrType); + _ = _dataSchemaGenerator.GenerateSchema(rightSchemaType, true, schemaRepository); + + referenceSchemaForRelationshipIdentifier = _relationshipIdentifierSchemaGenerator.GenerateSchema(relationship, schemaRepository); + } + else + { + referenceSchemaForRelationshipIdentifier = null; + } + + Type operationConstructedType = ChangeResourceTypeInSchemaType(operationOpenType, relationship.RightType); + _ = _dataContainerSchemaGenerator.GenerateSchema(operationConstructedType, relationship.RightType, true, false, schemaRepository); + + // This complicated implementation that generates a temporary schema stems from the fact that GetSchemaId takes a Type. + // We could feed it a constructed type with TLeftResource and TRightResource, but there's no way to include + // the relationship name because there's no runtime Type available for it. + string schemaId = _schemaIdSelector.GetRelationshipAtomicOperationSchemaId(relationship, operationCode); + + OpenApiSchema referenceSchemaForOperation = _defaultSchemaGenerator.GenerateSchema(operationConstructedType, schemaRepository); + OpenApiSchema fullSchemaForOperation = schemaRepository.Schemas[referenceSchemaForOperation.Reference.Id]; + fullSchemaForOperation.AdditionalPropertiesAllowed = false; + + OpenApiSchema inlineSchemaForOperation = fullSchemaForOperation.UnwrapLastExtendedSchema(); + SetOperationCode(inlineSchemaForOperation, operationCode, schemaRepository); + + if (referenceSchemaForRelationshipIdentifier != null) + { + inlineSchemaForOperation.Properties[JsonApiPropertyName.Ref] = referenceSchemaForRelationshipIdentifier.WrapInExtendedSchema(); + } + + inlineSchemaForOperation.Properties[JsonApiPropertyName.Data].Nullable = _resourceFieldValidationMetadataProvider.IsNullable(relationship); + + schemaRepository.ReplaceSchemaId(operationConstructedType, schemaId); + referenceSchemaForOperation.Reference.Id = schemaId; + + if (relationshipInAnyBaseResourceType != null) + { + RemoveProperties(inlineSchemaForOperation); + + string baseRelationshipSchemaId = _schemaIdSelector.GetRelationshipAtomicOperationSchemaId(relationshipInAnyBaseResourceType, operationCode); + ConsistencyGuard.ThrowIf(!schemaRepository.Schemas.ContainsKey(baseRelationshipSchemaId)); + + fullSchemaForOperation.AllOf[0] = new OpenApiSchema + { + Reference = new OpenApiReference + { + Id = baseRelationshipSchemaId, + Type = ReferenceType.Schema + } + }; + } + + string discriminatorValue = _schemaIdSelector.GetAtomicOperationDiscriminatorValue(operationCode, relationship); + MapInDiscriminator(referenceSchemaForOperation, discriminatorValue, schemaRepository); + + traceScope.TraceSucceeded(schemaId); + } + + private static WriteOperationKind GetKindOfRelationshipOperation(AtomicOperationCode operationCode) + { + WriteOperationKind? writeOperation = null; + + if (operationCode == AtomicOperationCode.Add) + { + writeOperation = WriteOperationKind.AddToRelationship; + } + else if (operationCode == AtomicOperationCode.Update) + { + writeOperation = WriteOperationKind.SetRelationship; + } + else if (operationCode == AtomicOperationCode.Remove) + { + writeOperation = WriteOperationKind.RemoveFromRelationship; + } + + ConsistencyGuard.ThrowIf(writeOperation == null); + return writeOperation.Value; + } + + private bool IsRelationshipEnabled(RelationshipAttribute relationship, WriteOperationKind writeOperation) + { + if (!_atomicOperationFilter.IsEnabled(relationship.LeftType, writeOperation)) + { + return false; + } + + if (relationship is HasOneAttribute hasOneRelationship && !IsToOneRelationshipEnabled(hasOneRelationship, writeOperation)) + { + return false; + } + + if (relationship is HasManyAttribute hasManyRelationship && !IsToManyRelationshipEnabled(hasManyRelationship, writeOperation)) + { + return false; + } + + return true; + } + + private static bool IsToOneRelationshipEnabled(HasOneAttribute relationship, WriteOperationKind writeOperation) + { + bool? isEnabled = null; + + if (writeOperation == WriteOperationKind.SetRelationship) + { + isEnabled = relationship.Capabilities.HasFlag(HasOneCapabilities.AllowSet); + } + + ConsistencyGuard.ThrowIf(isEnabled == null); + return isEnabled.Value; + } + + private static bool IsToManyRelationshipEnabled(HasManyAttribute relationship, WriteOperationKind writeOperation) + { + bool? isEnabled = null; + + if (writeOperation == WriteOperationKind.SetRelationship) + { + isEnabled = relationship.Capabilities.HasFlag(HasManyCapabilities.AllowSet); + } + else if (writeOperation == WriteOperationKind.AddToRelationship) + { + isEnabled = relationship.Capabilities.HasFlag(HasManyCapabilities.AllowAdd); + } + else if (writeOperation == WriteOperationKind.RemoveFromRelationship) + { + isEnabled = relationship.Capabilities.HasFlag(HasManyCapabilities.AllowRemove); + } + + ConsistencyGuard.ThrowIf(isEnabled == null); + return isEnabled.Value; + } + + private RelationshipAttribute? GetRelationshipEnabledInAnyBase(RelationshipAttribute relationship, WriteOperationKind writeOperation) + { + RelationshipAttribute? relationshipInBaseResourceType = relationship.LeftType.BaseType?.FindRelationshipByPublicName(relationship.PublicName); + + while (relationshipInBaseResourceType != null) + { + if (IsRelationshipEnabled(relationshipInBaseResourceType, writeOperation)) + { + return relationshipInBaseResourceType; + } + + relationshipInBaseResourceType = relationshipInBaseResourceType.LeftType.BaseType?.FindRelationshipByPublicName(relationship.PublicName); + } + + return null; + } + + private void GenerateSchemasForResponseDocument(SchemaRepository schemaRepository) + { + _ = _dataContainerSchemaGenerator.GenerateSchemaForCommonResourceDataInResponse(schemaRepository); + + foreach (ResourceType resourceType in _resourceGraph.GetResourceTypes()) + { + if (IsResourceTypeEnabled(resourceType, WriteOperationKind.CreateResource) || + IsResourceTypeEnabled(resourceType, WriteOperationKind.UpdateResource)) + { + _ = _dataContainerSchemaGenerator.GenerateSchema(typeof(AtomicResult), resourceType, false, false, schemaRepository); + } + } + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/DocumentSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/DocumentSchemaGenerator.cs new file mode 100644 index 0000000000..740b2fca43 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/DocumentSchemaGenerator.cs @@ -0,0 +1,69 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Documents; + +/// +/// Generates the OpenAPI component schema for a request and/or response document. +/// +internal abstract class DocumentSchemaGenerator +{ + private readonly SchemaGenerationTracer _schemaGenerationTracer; + private readonly MetaSchemaGenerator _metaSchemaGenerator; + private readonly LinksVisibilitySchemaGenerator _linksVisibilitySchemaGenerator; + private readonly IJsonApiOptions _options; + + protected DocumentSchemaGenerator(SchemaGenerationTracer schemaGenerationTracer, MetaSchemaGenerator metaSchemaGenerator, + LinksVisibilitySchemaGenerator linksVisibilitySchemaGenerator, IJsonApiOptions options) + { + ArgumentNullException.ThrowIfNull(schemaGenerationTracer); + ArgumentNullException.ThrowIfNull(metaSchemaGenerator); + ArgumentNullException.ThrowIfNull(linksVisibilitySchemaGenerator); + ArgumentNullException.ThrowIfNull(options); + + _schemaGenerationTracer = schemaGenerationTracer; + _metaSchemaGenerator = metaSchemaGenerator; + _linksVisibilitySchemaGenerator = linksVisibilitySchemaGenerator; + _options = options; + } + + public abstract bool CanGenerate(Type schemaType); + + public OpenApiSchema GenerateSchema(Type schemaType, SchemaRepository schemaRepository) + { + ArgumentNullException.ThrowIfNull(schemaType); + ArgumentNullException.ThrowIfNull(schemaRepository); + + if (schemaRepository.TryLookupByType(schemaType, out OpenApiSchema? referenceSchema)) + { + return referenceSchema; + } + + using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, schemaType); + + _metaSchemaGenerator.GenerateSchema(schemaRepository); + + referenceSchema = GenerateDocumentSchema(schemaType, schemaRepository); + OpenApiSchema fullSchema = schemaRepository.Schemas[referenceSchema.Reference.Id]; + + _linksVisibilitySchemaGenerator.UpdateSchemaForTopLevel(schemaType, fullSchema, schemaRepository); + + SetJsonApiVersion(fullSchema, schemaRepository); + + traceScope.TraceSucceeded(referenceSchema.Reference.Id); + return referenceSchema; + } + + protected abstract OpenApiSchema GenerateDocumentSchema(Type schemaType, SchemaRepository schemaRepository); + + private void SetJsonApiVersion(OpenApiSchema fullSchema, SchemaRepository schemaRepository) + { + if (fullSchema.Properties.ContainsKey(JsonApiPropertyName.Jsonapi) && !_options.IncludeJsonApiVersion) + { + fullSchema.Properties.Remove(JsonApiPropertyName.Jsonapi); + schemaRepository.Schemas.Remove(JsonApiPropertyName.Jsonapi); + } + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/ErrorResponseDocumentSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/ErrorResponseDocumentSchemaGenerator.cs new file mode 100644 index 0000000000..3d305e889b --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/ErrorResponseDocumentSchemaGenerator.cs @@ -0,0 +1,60 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; +using JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; +using JsonApiDotNetCore.Serialization.Objects; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Documents; + +/// +/// Generates the OpenAPI component schema for an error document. +/// +internal sealed class ErrorResponseDocumentSchemaGenerator : DocumentSchemaGenerator +{ + private static readonly Type ErrorObjectType = typeof(ErrorObject); + + private readonly SchemaGenerationTracer _schemaGenerationTracer; + private readonly SchemaGenerator _defaultSchemaGenerator; + private readonly MetaSchemaGenerator _metaSchemaGenerator; + + public ErrorResponseDocumentSchemaGenerator(SchemaGenerationTracer schemaGenerationTracer, SchemaGenerator defaultSchemaGenerator, + MetaSchemaGenerator metaSchemaGenerator, LinksVisibilitySchemaGenerator linksVisibilitySchemaGenerator, IJsonApiOptions options) + : base(schemaGenerationTracer, metaSchemaGenerator, linksVisibilitySchemaGenerator, options) + { + ArgumentNullException.ThrowIfNull(defaultSchemaGenerator); + + _schemaGenerationTracer = schemaGenerationTracer; + _defaultSchemaGenerator = defaultSchemaGenerator; + _metaSchemaGenerator = metaSchemaGenerator; + } + + public override bool CanGenerate(Type schemaType) + { + return schemaType == typeof(ErrorResponseDocument); + } + + protected override OpenApiSchema GenerateDocumentSchema(Type schemaType, SchemaRepository schemaRepository) + { + ArgumentNullException.ThrowIfNull(schemaType); + ArgumentNullException.ThrowIfNull(schemaRepository); + + OpenApiSchema referenceSchemaForErrorObject = GenerateSchemaForErrorObject(schemaRepository); + OpenApiSchema fullSchemaForErrorObject = schemaRepository.Schemas[referenceSchemaForErrorObject.Reference.Id]; + + OpenApiSchema referenceSchemaForMeta = _metaSchemaGenerator.GenerateSchema(schemaRepository); + fullSchemaForErrorObject.Properties[JsonApiPropertyName.Meta] = referenceSchemaForMeta.WrapInExtendedSchema(); + + return _defaultSchemaGenerator.GenerateSchema(schemaType, schemaRepository); + } + + private OpenApiSchema GenerateSchemaForErrorObject(SchemaRepository schemaRepository) + { + using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, ErrorObjectType); + + OpenApiSchema referenceSchema = _defaultSchemaGenerator.GenerateSchema(ErrorObjectType, schemaRepository); + + traceScope.TraceSucceeded(referenceSchema.Reference.Id); + return referenceSchema; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/ResourceOrRelationshipDocumentSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/ResourceOrRelationshipDocumentSchemaGenerator.cs new file mode 100644 index 0000000000..767f0d0143 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/ResourceOrRelationshipDocumentSchemaGenerator.cs @@ -0,0 +1,80 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Relationships; +using JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; +using JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Documents; + +/// +/// Generates the OpenAPI component schema for a resource/relationship request/response document. +/// +internal sealed class ResourceOrRelationshipDocumentSchemaGenerator : DocumentSchemaGenerator +{ + private static readonly Type[] RequestDocumentSchemaTypes = + [ + typeof(CreateRequestDocument<>), + typeof(UpdateRequestDocument<>), + typeof(ToOneInRequest<>), + typeof(NullableToOneInRequest<>), + typeof(ToManyInRequest<>) + ]; + + private static readonly Type[] ResponseDocumentSchemaTypes = + [ + typeof(CollectionResponseDocument<>), + typeof(PrimaryResponseDocument<>), + typeof(SecondaryResponseDocument<>), + typeof(NullableSecondaryResponseDocument<>), + typeof(IdentifierResponseDocument<>), + typeof(NullableIdentifierResponseDocument<>), + typeof(IdentifierCollectionResponseDocument<>) + ]; + + private readonly SchemaGenerator _defaultSchemaGenerator; + private readonly DataContainerSchemaGenerator _dataContainerSchemaGenerator; + private readonly IResourceGraph _resourceGraph; + + public ResourceOrRelationshipDocumentSchemaGenerator(SchemaGenerationTracer schemaGenerationTracer, SchemaGenerator defaultSchemaGenerator, + DataContainerSchemaGenerator dataContainerSchemaGenerator, MetaSchemaGenerator metaSchemaGenerator, + LinksVisibilitySchemaGenerator linksVisibilitySchemaGenerator, IJsonApiOptions options, IResourceGraph resourceGraph) + : base(schemaGenerationTracer, metaSchemaGenerator, linksVisibilitySchemaGenerator, options) + { + ArgumentNullException.ThrowIfNull(defaultSchemaGenerator); + ArgumentNullException.ThrowIfNull(dataContainerSchemaGenerator); + ArgumentNullException.ThrowIfNull(resourceGraph); + + _defaultSchemaGenerator = defaultSchemaGenerator; + _dataContainerSchemaGenerator = dataContainerSchemaGenerator; + _resourceGraph = resourceGraph; + } + + public override bool CanGenerate(Type schemaType) + { + Type schemaOpenType = schemaType.ConstructedToOpenType(); + return RequestDocumentSchemaTypes.Contains(schemaOpenType) || ResponseDocumentSchemaTypes.Contains(schemaOpenType); + } + + protected override OpenApiSchema GenerateDocumentSchema(Type schemaType, SchemaRepository schemaRepository) + { + ArgumentNullException.ThrowIfNull(schemaType); + ArgumentNullException.ThrowIfNull(schemaRepository); + + var resourceSchemaType = ResourceSchemaType.Create(schemaType, _resourceGraph); + bool isRequestSchema = RequestDocumentSchemaTypes.Contains(resourceSchemaType.SchemaOpenType); + + _ = _dataContainerSchemaGenerator.GenerateSchema(schemaType, resourceSchemaType.ResourceType, isRequestSchema, !isRequestSchema, schemaRepository); + + OpenApiSchema? referenceSchemaForDocument = _defaultSchemaGenerator.GenerateSchema(schemaType, schemaRepository); + OpenApiSchema inlineSchemaForDocument = schemaRepository.Schemas[referenceSchemaForDocument.Reference.Id].UnwrapLastExtendedSchema(); + + if (JsonApiSchemaFacts.HasNullableDataProperty(resourceSchemaType.SchemaOpenType)) + { + inlineSchemaForDocument.Properties[JsonApiPropertyName.Data].Nullable = true; + } + + return referenceSchemaForDocument; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/GenerationCacheSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/GenerationCacheSchemaGenerator.cs new file mode 100644 index 0000000000..beba632ebf --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/GenerationCacheSchemaGenerator.cs @@ -0,0 +1,93 @@ +using System.Reflection; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata; +using Microsoft.AspNetCore.Mvc.Abstractions; +using Microsoft.AspNetCore.Mvc.Infrastructure; +using Microsoft.OpenApi.Any; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators; + +/// +/// Provides access to cached state, which is stored in a temporary schema in during schema generation. +/// +internal sealed class GenerationCacheSchemaGenerator +{ + private const string HasAtomicOperationsEndpointPropertyName = "HasAtomicOperationsEndpoint"; + public const string SchemaId = "__JsonApiSchemaGenerationCache__"; + + private readonly SchemaGenerationTracer _schemaGenerationTracer; + private readonly IActionDescriptorCollectionProvider _defaultProvider; + private readonly JsonApiEndpointMetadataProvider _jsonApiEndpointMetadataProvider; + + public GenerationCacheSchemaGenerator(SchemaGenerationTracer schemaGenerationTracer, IActionDescriptorCollectionProvider defaultProvider, + JsonApiEndpointMetadataProvider jsonApiEndpointMetadataProvider) + { + ArgumentNullException.ThrowIfNull(schemaGenerationTracer); + ArgumentNullException.ThrowIfNull(defaultProvider); + ArgumentNullException.ThrowIfNull(jsonApiEndpointMetadataProvider); + + _schemaGenerationTracer = schemaGenerationTracer; + _defaultProvider = defaultProvider; + _jsonApiEndpointMetadataProvider = jsonApiEndpointMetadataProvider; + } + + public bool HasAtomicOperationsEndpoint(SchemaRepository schemaRepository) + { + ArgumentNullException.ThrowIfNull(schemaRepository); + + OpenApiSchema fullSchema = GenerateFullSchema(schemaRepository); + + var hasAtomicOperationsEndpoint = (OpenApiBoolean)fullSchema.Properties[HasAtomicOperationsEndpointPropertyName].Default; + return hasAtomicOperationsEndpoint.Value; + } + + private OpenApiSchema GenerateFullSchema(SchemaRepository schemaRepository) + { + if (schemaRepository.Schemas.TryGetValue(SchemaId, out OpenApiSchema? fullSchema)) + { + return fullSchema; + } + + using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this); + + bool hasAtomicOperationsEndpoint = EvaluateHasAtomicOperationsEndpoint(); + + fullSchema = new OpenApiSchema + { + Type = "object", + Properties = new Dictionary + { + [HasAtomicOperationsEndpointPropertyName] = new() + { + Type = "boolean", + Default = new OpenApiBoolean(hasAtomicOperationsEndpoint) + } + } + }; + + schemaRepository.AddDefinition(SchemaId, fullSchema); + + traceScope.TraceSucceeded(SchemaId); + return fullSchema; + } + + private bool EvaluateHasAtomicOperationsEndpoint() + { + IEnumerable actionDescriptors = + _defaultProvider.ActionDescriptors.Items.Where(JsonApiActionDescriptorCollectionProvider.IsVisibleJsonApiEndpoint); + + foreach (ActionDescriptor actionDescriptor in actionDescriptors) + { + MethodInfo actionMethod = actionDescriptor.GetActionMethod(); + JsonApiEndpointMetadataContainer endpointMetadataContainer = _jsonApiEndpointMetadataProvider.Get(actionMethod); + + if (endpointMetadataContainer.RequestMetadata is AtomicOperationsRequestMetadata) + { + return true; + } + } + + return false; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/JsonApiSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/JsonApiSchemaGenerator.cs new file mode 100644 index 0000000000..19d94eb48e --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/JsonApiSchemaGenerator.cs @@ -0,0 +1,70 @@ +using System.Reflection; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; +using JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Documents; +using Microsoft.AspNetCore.Mvc.ApiExplorer; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators; + +internal sealed class JsonApiSchemaGenerator : ISchemaGenerator +{ + private readonly ResourceIdSchemaGenerator _resourceIdSchemaGenerator; + private readonly DocumentSchemaGenerator[] _documentSchemaGenerators; + + public JsonApiSchemaGenerator(ResourceIdSchemaGenerator resourceIdSchemaGenerator, IEnumerable documentSchemaGenerators) + { + ArgumentNullException.ThrowIfNull(resourceIdSchemaGenerator); + ArgumentNullException.ThrowIfNull(documentSchemaGenerators); + + _resourceIdSchemaGenerator = resourceIdSchemaGenerator; + _documentSchemaGenerators = documentSchemaGenerators as DocumentSchemaGenerator[] ?? documentSchemaGenerators.ToArray(); + } + + public OpenApiSchema GenerateSchema(Type schemaType, SchemaRepository schemaRepository, MemberInfo? memberInfo = null, ParameterInfo? parameterInfo = null, + ApiParameterRouteInfo? routeInfo = null) + { + ArgumentNullException.ThrowIfNull(schemaType); + ArgumentNullException.ThrowIfNull(schemaRepository); + + if (parameterInfo is { Name: "id" } && IsJsonApiParameter(parameterInfo)) + { + return _resourceIdSchemaGenerator.GenerateSchema(schemaType, schemaRepository); + } + + DocumentSchemaGenerator schemaGenerator = GetDocumentSchemaGenerator(schemaType); + OpenApiSchema referenceSchema = schemaGenerator.GenerateSchema(schemaType, schemaRepository); + + if (memberInfo != null || parameterInfo != null) + { + // For unknown reasons, Swashbuckle chooses to wrap request bodies in allOf, but not response bodies. + // We just replicate that behavior here. See https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/861#issuecomment-1373631712. + referenceSchema = referenceSchema.WrapInExtendedSchema(); + } + + return referenceSchema; + } + + private static bool IsJsonApiParameter(ParameterInfo parameter) + { + return parameter.Member.DeclaringType != null && parameter.Member.DeclaringType.IsAssignableTo(typeof(CoreJsonApiController)); + } + + private DocumentSchemaGenerator GetDocumentSchemaGenerator(Type schemaType) + { + DocumentSchemaGenerator? generator = null; + + foreach (DocumentSchemaGenerator documentSchemaGenerator in _documentSchemaGenerators) + { + if (documentSchemaGenerator.CanGenerate(schemaType)) + { + generator = documentSchemaGenerator; + break; + } + } + + ConsistencyGuard.ThrowIf(generator == null); + return generator; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaRepositoryExtensions.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaRepositoryExtensions.cs new file mode 100644 index 0000000000..669c50b4e0 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaRepositoryExtensions.cs @@ -0,0 +1,63 @@ +using System.Reflection; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +internal static class SchemaRepositoryExtensions +{ + private const string ReservedIdsFieldName = "_reservedIds"; + private static readonly FieldInfo ReservedIdsField = GetReservedIdsField(); + + private static FieldInfo GetReservedIdsField() + { + FieldInfo? field = typeof(SchemaRepository).GetField(ReservedIdsFieldName, BindingFlags.Instance | BindingFlags.NonPublic); + + if (field == null) + { + throw new InvalidOperationException($"Failed to locate private field '{ReservedIdsFieldName}' " + + $"in type '{typeof(SchemaRepository).FullName}' in assembly '{typeof(SchemaRepository).Assembly.FullName}'."); + } + + if (field.FieldType != typeof(Dictionary)) + { + throw new InvalidOperationException($"Unexpected type '{field.FieldType}' of private field '{ReservedIdsFieldName}' " + + $"in type '{typeof(SchemaRepository).FullName}' in assembly '{typeof(SchemaRepository).Assembly.FullName}'."); + } + + return field; + } + + public static OpenApiSchema LookupByType(this SchemaRepository schemaRepository, Type schemaType) + { + ArgumentNullException.ThrowIfNull(schemaRepository); + ArgumentNullException.ThrowIfNull(schemaType); + + if (!schemaRepository.TryLookupByType(schemaType, out OpenApiSchema? referenceSchema)) + { + throw new InvalidOperationException($"Reference schema for '{schemaType.Name}' does not exist."); + } + + return referenceSchema; + } + + public static void ReplaceSchemaId(this SchemaRepository schemaRepository, Type oldSchemaType, string newSchemaId) + { + ArgumentNullException.ThrowIfNull(schemaRepository); + ArgumentNullException.ThrowIfNull(oldSchemaType); + ArgumentException.ThrowIfNullOrEmpty(newSchemaId); + + if (schemaRepository.TryLookupByType(oldSchemaType, out OpenApiSchema? referenceSchema)) + { + string oldSchemaId = referenceSchema.Reference.Id; + + OpenApiSchema fullSchema = schemaRepository.Schemas[oldSchemaId]; + + schemaRepository.Schemas.Remove(oldSchemaId); + schemaRepository.Schemas.Add(newSchemaId, fullSchema); + + var reservedIds = (Dictionary)ReservedIdsField.GetValue(schemaRepository)!; + reservedIds.Remove(oldSchemaType); + } + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ServiceCollectionExtensions.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ServiceCollectionExtensions.cs new file mode 100644 index 0000000000..df5247d9de --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ServiceCollectionExtensions.cs @@ -0,0 +1,115 @@ +using System.Diagnostics.CodeAnalysis; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata; +using JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators; +using JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; +using JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Documents; +using JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; +using JsonApiDotNetCore.Serialization.Response; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ApiExplorer; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Options; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +public static class ServiceCollectionExtensions +{ + /// + /// Configures OpenAPI for JsonApiDotNetCore using Swashbuckle. + /// + [Experimental("JADNC_OA_001", UrlFormat = "https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/master/docs/usage/openapi.md")] + public static void AddOpenApiForJsonApi(this IServiceCollection services, Action? configureSwaggerGenOptions = null) + { + ArgumentNullException.ThrowIfNull(services); + + AddCustomApiExplorer(services); + AddCustomSwaggerComponents(services); + AddSwaggerGenerator(services); + + if (configureSwaggerGenOptions != null) + { + services.Configure(configureSwaggerGenOptions); + } + + services.AddSingleton(); + services.TryAddSingleton(); + services.Replace(ServiceDescriptor.Singleton()); + } + + private static void AddCustomApiExplorer(IServiceCollection services) + { + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + + // Not using TryAddSingleton, see https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/1463. + services.Replace(ServiceDescriptor.Singleton(serviceProvider => + { + var actionDescriptorCollectionProvider = serviceProvider.GetRequiredService(); + var apiDescriptionProviders = serviceProvider.GetRequiredService>(); + + return new ApiDescriptionGroupCollectionProvider(actionDescriptorCollectionProvider, apiDescriptionProviders); + })); + + AddApiExplorer(services); + + services.AddSingleton, ConfigureMvcOptions>(); + } + + private static void AddApiExplorer(IServiceCollection services) + { + // The code below was copied from the implementation of MvcApiExplorerMvcCoreBuilderExtensions.AddApiExplorer(), + // so we don't need to take IMvcCoreBuilder as an input parameter. + + services.TryAddEnumerable(ServiceDescriptor.Transient()); + } + + private static void AddCustomSwaggerComponents(IServiceCollection services) + { + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + } + + private static void AddSwaggerGenerator(IServiceCollection services) + { + AddSchemaGenerators(services); + + services.TryAddSingleton(); + services.AddSingleton(); + + services.AddSwaggerGen(); + services.AddSingleton, ConfigureSwaggerGenOptions>(); + } + + private static void AddSchemaGenerators(IServiceCollection services) + { + services.TryAddSingleton(); + services.TryAddSingleton(); + + services.TryAddEnumerable(ServiceDescriptor.Singleton()); + services.TryAddEnumerable(ServiceDescriptor.Singleton()); + services.TryAddEnumerable(ServiceDescriptor.Singleton()); + + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + + services.TryAddSingleton(); + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SetSchemaTypeToObjectDocumentFilter.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SetSchemaTypeToObjectDocumentFilter.cs new file mode 100644 index 0000000000..2764f868e6 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SetSchemaTypeToObjectDocumentFilter.cs @@ -0,0 +1,23 @@ +using JetBrains.Annotations; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +internal sealed class SetSchemaTypeToObjectDocumentFilter : IDocumentFilter +{ + internal const string RequiresRootObjectTypeKey = "x-requires-root-object-type"; + + public void Apply(OpenApiDocument document, DocumentFilterContext context) + { + foreach (OpenApiSchema schema in document.Components.Schemas.Values) + { + if (schema.Extensions.ContainsKey(RequiresRootObjectTypeKey)) + { + schema.Type = "object"; + schema.Extensions.Remove(RequiresRootObjectTypeKey); + } + } + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/DocumentationOpenApiOperationFilter.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/DocumentationOpenApiOperationFilter.cs new file mode 100644 index 0000000000..1b5c0d5f4c --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/DocumentationOpenApiOperationFilter.cs @@ -0,0 +1,596 @@ +using System.Net; +using System.Reflection; +using Humanizer; +using JetBrains.Annotations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; +using Microsoft.AspNetCore.Mvc.ApiExplorer; +using Microsoft.Net.Http.Headers; +using Microsoft.OpenApi.Any; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; + +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +internal sealed class DocumentationOpenApiOperationFilter : IOperationFilter +{ + private const string GetPrimaryName = nameof(BaseJsonApiController, int>.GetAsync); + private const string GetSecondaryName = nameof(BaseJsonApiController, int>.GetSecondaryAsync); + private const string GetRelationshipName = nameof(BaseJsonApiController, int>.GetRelationshipAsync); + private const string PostResourceName = nameof(BaseJsonApiController, int>.PostAsync); + private const string PostRelationshipName = nameof(BaseJsonApiController, int>.PostRelationshipAsync); + private const string PatchResourceName = nameof(BaseJsonApiController, int>.PatchAsync); + private const string PatchRelationshipName = nameof(BaseJsonApiController, int>.PatchRelationshipAsync); + private const string DeleteResourceName = nameof(BaseJsonApiController, int>.DeleteAsync); + private const string DeleteRelationshipName = nameof(BaseJsonApiController, int>.DeleteRelationshipAsync); + private const string PostOperationsName = nameof(BaseJsonApiOperationsController.PostOperationsAsync); + + private const string TextCompareETag = + "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched."; + + private const string TextCompletedSuccessfully = "The operation completed successfully."; + private const string TextNotModified = "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header."; + private const string TextQueryStringBad = "The query string is invalid."; + private const string TextRequestBodyBad = "The request body is missing or malformed."; + private const string TextQueryStringOrRequestBodyBad = "The query string is invalid or the request body is missing or malformed."; + private const string TextConflict = "The request body contains conflicting information or another resource with the same ID already exists."; + private const string TextRequestBodyIncompatibleIdOrType = "A resource type or identifier in the request body is incompatible."; + private const string TextRequestBodyValidationFailed = "Validation of the request body failed."; + private const string TextRequestBodyClientId = "Client-generated IDs cannot be used at this endpoint."; + + private const string ResourceQueryStringParameters = + "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/" + + "[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/" + + "[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/" + + "[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters."; + + private const string RelationshipQueryStringParameters = "For syntax, see the documentation for the " + + "[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/" + + "[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/" + + "[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters."; + + private readonly IJsonApiOptions _options; + private readonly IControllerResourceMapping _controllerResourceMapping; + private readonly ResourceFieldValidationMetadataProvider _resourceFieldValidationMetadataProvider; + + public DocumentationOpenApiOperationFilter(IJsonApiOptions options, IControllerResourceMapping controllerResourceMapping, + ResourceFieldValidationMetadataProvider resourceFieldValidationMetadataProvider) + { + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(controllerResourceMapping); + ArgumentNullException.ThrowIfNull(resourceFieldValidationMetadataProvider); + + _options = options; + _controllerResourceMapping = controllerResourceMapping; + _resourceFieldValidationMetadataProvider = resourceFieldValidationMetadataProvider; + } + + public void Apply(OpenApiOperation operation, OperationFilterContext context) + { + ArgumentNullException.ThrowIfNull(operation); + ArgumentNullException.ThrowIfNull(context); + + bool hasHeadVerb = context.ApiDescription.HttpMethod == "HEAD"; + + if (hasHeadVerb) + { + operation.Responses.Clear(); + } + + MethodInfo actionMethod = context.ApiDescription.ActionDescriptor.GetActionMethod(); + string actionName = context.MethodInfo.Name; + ResourceType? resourceType = _controllerResourceMapping.GetResourceTypeForController(actionMethod.ReflectedType); + + if (resourceType != null) + { + switch (actionName) + { + case GetPrimaryName or PostResourceName or PatchResourceName or DeleteResourceName: + { + switch (actionName) + { + case GetPrimaryName: + { + ApplyGetPrimary(operation, resourceType, hasHeadVerb); + break; + } + case PostResourceName: + { + ApplyPostResource(operation, resourceType); + break; + } + case PatchResourceName: + { + ApplyPatchResource(operation, resourceType); + break; + } + case DeleteResourceName: + { + ApplyDeleteResource(operation, resourceType); + break; + } + } + + break; + } + case GetSecondaryName or GetRelationshipName or PostRelationshipName or PatchRelationshipName or DeleteRelationshipName: + { + RelationshipAttribute relationship = GetRelationshipFromRoute(context.ApiDescription, resourceType); + + switch (actionName) + { + case GetSecondaryName: + { + ApplyGetSecondary(operation, relationship, hasHeadVerb); + break; + } + case GetRelationshipName: + { + ApplyGetRelationship(operation, relationship, hasHeadVerb); + break; + } + case PostRelationshipName: + { + ApplyPostRelationship(operation, relationship); + break; + } + case PatchRelationshipName: + { + ApplyPatchRelationship(operation, relationship); + break; + } + case DeleteRelationshipName: + { + ApplyDeleteRelationship(operation, relationship); + break; + } + } + + break; + } + } + } + else if (actionName == PostOperationsName) + { + ApplyPostOperations(operation); + } + } + + private static void ApplyGetPrimary(OpenApiOperation operation, ResourceType resourceType, bool hasHeadVerb) + { + if (operation.Parameters.Count == 0) + { + if (hasHeadVerb) + { + SetOperationSummary(operation, $"Retrieves a collection of {resourceType} without returning them."); + SetOperationRemarks(operation, TextCompareETag); + SetResponseDescription(operation.Responses, HttpStatusCode.OK, TextCompletedSuccessfully); + SetResponseHeaderETag(operation.Responses, HttpStatusCode.OK); + SetResponseHeaderContentLength(operation.Responses, HttpStatusCode.OK); + SetResponseDescription(operation.Responses, HttpStatusCode.NotModified, TextNotModified); + SetResponseHeaderETag(operation.Responses, HttpStatusCode.NotModified); + } + else + { + SetOperationSummary(operation, $"Retrieves a collection of {resourceType}."); + + SetResponseDescription(operation.Responses, HttpStatusCode.OK, + $"Successfully returns the found {resourceType}, or an empty array if none were found."); + + SetResponseHeaderETag(operation.Responses, HttpStatusCode.OK); + SetResponseDescription(operation.Responses, HttpStatusCode.NotModified, TextNotModified); + SetResponseHeaderETag(operation.Responses, HttpStatusCode.NotModified); + } + + AddQueryStringParameters(operation, false); + AddRequestHeaderIfNoneMatch(operation); + SetResponseDescription(operation.Responses, HttpStatusCode.BadRequest, TextQueryStringBad); + } + else if (operation.Parameters.Count == 1) + { + string singularName = resourceType.PublicName.Singularize(); + + if (hasHeadVerb) + { + SetOperationSummary(operation, $"Retrieves an individual {singularName} by its identifier without returning it."); + SetOperationRemarks(operation, TextCompareETag); + SetResponseDescription(operation.Responses, HttpStatusCode.OK, TextCompletedSuccessfully); + SetResponseHeaderETag(operation.Responses, HttpStatusCode.OK); + SetResponseHeaderContentLength(operation.Responses, HttpStatusCode.OK); + SetResponseDescription(operation.Responses, HttpStatusCode.NotModified, TextNotModified); + SetResponseHeaderETag(operation.Responses, HttpStatusCode.NotModified); + } + else + { + SetOperationSummary(operation, $"Retrieves an individual {singularName} by its identifier."); + SetResponseDescription(operation.Responses, HttpStatusCode.OK, $"Successfully returns the found {singularName}."); + SetResponseHeaderETag(operation.Responses, HttpStatusCode.OK); + SetResponseDescription(operation.Responses, HttpStatusCode.NotModified, TextNotModified); + SetResponseHeaderETag(operation.Responses, HttpStatusCode.NotModified); + } + + SetParameterDescription(operation.Parameters[0], $"The identifier of the {singularName} to retrieve."); + AddQueryStringParameters(operation, false); + AddRequestHeaderIfNoneMatch(operation); + SetResponseDescription(operation.Responses, HttpStatusCode.BadRequest, TextQueryStringBad); + SetResponseDescription(operation.Responses, HttpStatusCode.NotFound, $"The {singularName} does not exist."); + } + } + + private void ApplyPostResource(OpenApiOperation operation, ResourceType resourceType) + { + string singularName = resourceType.PublicName.Singularize(); + + SetOperationSummary(operation, $"Creates a new {singularName}."); + AddQueryStringParameters(operation, false); + SetRequestBodyDescription(operation.RequestBody, $"The attributes and relationships of the {singularName} to create."); + + SetResponseDescription(operation.Responses, HttpStatusCode.Created, + $"The {singularName} was successfully created, which resulted in additional changes. The newly created {singularName} is returned."); + + SetResponseHeaderLocation(operation.Responses, HttpStatusCode.Created, singularName); + + SetResponseDescription(operation.Responses, HttpStatusCode.NoContent, + $"The {singularName} was successfully created, which did not result in additional changes."); + + SetResponseDescription(operation.Responses, HttpStatusCode.BadRequest, TextQueryStringOrRequestBodyBad); + + ClientIdGenerationMode clientIdGeneration = resourceType.ClientIdGeneration ?? _options.ClientIdGeneration; + + if (clientIdGeneration == ClientIdGenerationMode.Forbidden) + { + SetResponseDescription(operation.Responses, HttpStatusCode.Forbidden, TextRequestBodyClientId); + } + + SetResponseDescription(operation.Responses, HttpStatusCode.NotFound, "A related resource does not exist."); + SetResponseDescription(operation.Responses, HttpStatusCode.Conflict, TextConflict); + SetResponseDescription(operation.Responses, HttpStatusCode.UnprocessableEntity, TextRequestBodyValidationFailed); + } + + private void ApplyPatchResource(OpenApiOperation operation, ResourceType resourceType) + { + string singularName = resourceType.PublicName.Singularize(); + + SetOperationSummary(operation, $"Updates an existing {singularName}."); + SetParameterDescription(operation.Parameters[0], $"The identifier of the {singularName} to update."); + AddQueryStringParameters(operation, false); + + SetRequestBodyDescription(operation.RequestBody, + $"The attributes and relationships of the {singularName} to update. Omitted fields are left unchanged."); + + SetResponseDescription(operation.Responses, HttpStatusCode.OK, + $"The {singularName} was successfully updated, which resulted in additional changes. The updated {singularName} is returned."); + + SetResponseDescription(operation.Responses, HttpStatusCode.NoContent, + $"The {singularName} was successfully updated, which did not result in additional changes."); + + SetResponseDescription(operation.Responses, HttpStatusCode.BadRequest, TextQueryStringOrRequestBodyBad); + SetResponseDescription(operation.Responses, HttpStatusCode.NotFound, $"The {singularName} or a related resource does not exist."); + SetResponseDescription(operation.Responses, HttpStatusCode.Conflict, TextRequestBodyIncompatibleIdOrType); + SetResponseDescription(operation.Responses, HttpStatusCode.UnprocessableEntity, TextRequestBodyValidationFailed); + } + + private void ApplyDeleteResource(OpenApiOperation operation, ResourceType resourceType) + { + string singularName = resourceType.PublicName.Singularize(); + + SetOperationSummary(operation, $"Deletes an existing {singularName} by its identifier."); + SetParameterDescription(operation.Parameters[0], $"The identifier of the {singularName} to delete."); + SetResponseDescription(operation.Responses, HttpStatusCode.NoContent, $"The {singularName} was successfully deleted."); + SetResponseDescription(operation.Responses, HttpStatusCode.NotFound, $"The {singularName} does not exist."); + } + + private static void ApplyGetSecondary(OpenApiOperation operation, RelationshipAttribute relationship, bool hasHeadVerb) + { + string singularLeftName = relationship.LeftType.PublicName.Singularize(); + string rightName = relationship is HasOneAttribute ? relationship.RightType.PublicName.Singularize() : relationship.RightType.PublicName; + + if (hasHeadVerb) + { + SetOperationSummary(operation, + relationship is HasOneAttribute + ? $"Retrieves the related {rightName} of an individual {singularLeftName}'s {relationship} relationship without returning it." + : $"Retrieves the related {rightName} of an individual {singularLeftName}'s {relationship} relationship without returning them."); + + SetOperationRemarks(operation, TextCompareETag); + SetResponseDescription(operation.Responses, HttpStatusCode.OK, TextCompletedSuccessfully); + SetResponseHeaderETag(operation.Responses, HttpStatusCode.OK); + SetResponseHeaderContentLength(operation.Responses, HttpStatusCode.OK); + SetResponseDescription(operation.Responses, HttpStatusCode.NotModified, TextNotModified); + SetResponseHeaderETag(operation.Responses, HttpStatusCode.NotModified); + } + else + { + SetOperationSummary(operation, $"Retrieves the related {rightName} of an individual {singularLeftName}'s {relationship} relationship."); + + SetResponseDescription(operation.Responses, HttpStatusCode.OK, + relationship is HasOneAttribute + ? $"Successfully returns the found {rightName}, or null if it was not found." + : $"Successfully returns the found {rightName}, or an empty array if none were found."); + + SetResponseHeaderETag(operation.Responses, HttpStatusCode.OK); + SetResponseDescription(operation.Responses, HttpStatusCode.NotModified, TextNotModified); + SetResponseHeaderETag(operation.Responses, HttpStatusCode.NotModified); + } + + SetParameterDescription(operation.Parameters[0], $"The identifier of the {singularLeftName} whose related {rightName} to retrieve."); + AddQueryStringParameters(operation, false); + AddRequestHeaderIfNoneMatch(operation); + SetResponseDescription(operation.Responses, HttpStatusCode.BadRequest, TextQueryStringBad); + SetResponseDescription(operation.Responses, HttpStatusCode.NotFound, $"The {singularLeftName} does not exist."); + } + + private static void ApplyGetRelationship(OpenApiOperation operation, RelationshipAttribute relationship, bool hasHeadVerb) + { + string singularLeftName = relationship.LeftType.PublicName.Singularize(); + string singularRightName = relationship.RightType.PublicName.Singularize(); + string ident = relationship is HasOneAttribute ? "identity" : "identities"; + + if (hasHeadVerb) + { + SetOperationSummary(operation, + relationship is HasOneAttribute + ? $"Retrieves the related {singularRightName} {ident} of an individual {singularLeftName}'s {relationship} relationship without returning it." + : $"Retrieves the related {singularRightName} {ident} of an individual {singularLeftName}'s {relationship} relationship without returning them."); + + SetOperationRemarks(operation, TextCompareETag); + SetResponseDescription(operation.Responses, HttpStatusCode.OK, TextCompletedSuccessfully); + SetResponseHeaderETag(operation.Responses, HttpStatusCode.OK); + SetResponseHeaderContentLength(operation.Responses, HttpStatusCode.OK); + SetResponseDescription(operation.Responses, HttpStatusCode.NotModified, TextNotModified); + SetResponseHeaderETag(operation.Responses, HttpStatusCode.NotModified); + } + else + { + SetOperationSummary(operation, + $"Retrieves the related {singularRightName} {ident} of an individual {singularLeftName}'s {relationship} relationship."); + + SetResponseDescription(operation.Responses, HttpStatusCode.OK, + relationship is HasOneAttribute + ? $"Successfully returns the found {singularRightName} {ident}, or null if it was not found." + : $"Successfully returns the found {singularRightName} {ident}, or an empty array if none were found."); + + SetResponseHeaderETag(operation.Responses, HttpStatusCode.OK); + SetResponseDescription(operation.Responses, HttpStatusCode.NotModified, TextNotModified); + SetResponseHeaderETag(operation.Responses, HttpStatusCode.NotModified); + } + + SetParameterDescription(operation.Parameters[0], $"The identifier of the {singularLeftName} whose related {singularRightName} {ident} to retrieve."); + AddQueryStringParameters(operation, true); + AddRequestHeaderIfNoneMatch(operation); + SetResponseDescription(operation.Responses, HttpStatusCode.BadRequest, TextQueryStringBad); + SetResponseDescription(operation.Responses, HttpStatusCode.NotFound, $"The {singularLeftName} does not exist."); + } + + private void ApplyPostRelationship(OpenApiOperation operation, RelationshipAttribute relationship) + { + string singularLeftName = relationship.LeftType.PublicName.Singularize(); + string rightName = relationship.RightType.PublicName; + + SetOperationSummary(operation, $"Adds existing {rightName} to the {relationship} relationship of an individual {singularLeftName}."); + SetParameterDescription(operation.Parameters[0], $"The identifier of the {singularLeftName} to add {rightName} to."); + SetRequestBodyDescription(operation.RequestBody, $"The identities of the {rightName} to add to the {relationship} relationship."); + + SetResponseDescription(operation.Responses, HttpStatusCode.NoContent, + $"The {rightName} were successfully added, which did not result in additional changes."); + + SetResponseDescription(operation.Responses, HttpStatusCode.BadRequest, TextRequestBodyBad); + SetResponseDescription(operation.Responses, HttpStatusCode.NotFound, $"The {singularLeftName} or a related resource does not exist."); + SetResponseDescription(operation.Responses, HttpStatusCode.Conflict, TextConflict); + SetResponseDescription(operation.Responses, HttpStatusCode.UnprocessableEntity, TextRequestBodyValidationFailed); + } + + private void ApplyPatchRelationship(OpenApiOperation operation, RelationshipAttribute relationship) + { + bool isOptional = _resourceFieldValidationMetadataProvider.IsNullable(relationship); + string singularLeftName = relationship.LeftType.PublicName.Singularize(); + string rightName = relationship is HasOneAttribute ? relationship.RightType.PublicName.Singularize() : relationship.RightType.PublicName; + + SetOperationSummary(operation, + relationship is HasOneAttribute + ? isOptional + ? $"Clears or assigns an existing {rightName} to the {relationship} relationship of an individual {singularLeftName}." + : $"Assigns an existing {rightName} to the {relationship} relationship of an individual {singularLeftName}." + : $"Assigns existing {rightName} to the {relationship} relationship of an individual {singularLeftName}."); + + SetParameterDescription(operation.Parameters[0], + isOptional + ? $"The identifier of the {singularLeftName} whose {relationship} relationship to assign or clear." + : $"The identifier of the {singularLeftName} whose {relationship} relationship to assign."); + + SetRequestBodyDescription(operation.RequestBody, + relationship is HasOneAttribute + ? isOptional + ? $"The identity of the {rightName} to assign to the {relationship} relationship, or null to clear the relationship." + : $"The identity of the {rightName} to assign to the {relationship} relationship." + : $"The identities of the {rightName} to assign to the {relationship} relationship, or an empty array to clear the relationship."); + + SetResponseDescription(operation.Responses, HttpStatusCode.NoContent, + $"The {relationship} relationship was successfully updated, which did not result in additional changes."); + + SetResponseDescription(operation.Responses, HttpStatusCode.BadRequest, TextRequestBodyBad); + SetResponseDescription(operation.Responses, HttpStatusCode.NotFound, $"The {singularLeftName} or a related resource does not exist."); + SetResponseDescription(operation.Responses, HttpStatusCode.Conflict, TextConflict); + SetResponseDescription(operation.Responses, HttpStatusCode.UnprocessableEntity, TextRequestBodyValidationFailed); + } + + private void ApplyDeleteRelationship(OpenApiOperation operation, RelationshipAttribute relationship) + { + string singularLeftName = relationship.LeftType.PublicName.Singularize(); + string rightName = relationship.RightType.PublicName; + + SetOperationSummary(operation, $"Removes existing {rightName} from the {relationship} relationship of an individual {singularLeftName}."); + SetParameterDescription(operation.Parameters[0], $"The identifier of the {singularLeftName} to remove {rightName} from."); + SetRequestBodyDescription(operation.RequestBody, $"The identities of the {rightName} to remove from the {relationship} relationship."); + + SetResponseDescription(operation.Responses, HttpStatusCode.NoContent, + $"The {rightName} were successfully removed, which did not result in additional changes."); + + SetResponseDescription(operation.Responses, HttpStatusCode.BadRequest, TextRequestBodyBad); + SetResponseDescription(operation.Responses, HttpStatusCode.NotFound, $"The {singularLeftName} or a related resource does not exist."); + SetResponseDescription(operation.Responses, HttpStatusCode.Conflict, TextConflict); + SetResponseDescription(operation.Responses, HttpStatusCode.UnprocessableEntity, TextRequestBodyValidationFailed); + } + + private static RelationshipAttribute GetRelationshipFromRoute(ApiDescription apiDescription, ResourceType resourceType) + { + ConsistencyGuard.ThrowIf(apiDescription.RelativePath == null); + + string relationshipName = apiDescription.RelativePath.Split('/').Last(); + return resourceType.GetRelationshipByPublicName(relationshipName); + } + + private static void SetOperationSummary(OpenApiOperation operation, string description) + { + operation.Summary = XmlCommentsTextHelper.Humanize(description); + } + + private static void SetOperationRemarks(OpenApiOperation operation, string description) + { + operation.Description = XmlCommentsTextHelper.Humanize(description); + } + + private static void SetParameterDescription(OpenApiParameter parameter, string description) + { + parameter.Description = XmlCommentsTextHelper.Humanize(description); + } + + private static void SetRequestBodyDescription(OpenApiRequestBody requestBody, string description) + { + requestBody.Description = XmlCommentsTextHelper.Humanize(description); + } + + private static void SetResponseDescription(OpenApiResponses responses, HttpStatusCode statusCode, string description) + { + OpenApiResponse response = GetOrAddResponse(responses, statusCode); + response.Description = XmlCommentsTextHelper.Humanize(description); + } + + private static void SetResponseHeaderETag(OpenApiResponses responses, HttpStatusCode statusCode) + { + OpenApiResponse response = GetOrAddResponse(responses, statusCode); + + response.Headers[HeaderNames.ETag] = new OpenApiHeader + { + Description = "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + Required = true, + Schema = new OpenApiSchema + { + Type = "string" + } + }; + } + + private static void SetResponseHeaderContentLength(OpenApiResponses responses, HttpStatusCode statusCode) + { + OpenApiResponse response = GetOrAddResponse(responses, statusCode); + + response.Headers[HeaderNames.ContentLength] = new OpenApiHeader + { + Description = "Size of the HTTP response body, in bytes.", + Required = true, + Schema = new OpenApiSchema + { + Type = "integer", + Format = "int64" + } + }; + } + + private static void SetResponseHeaderLocation(OpenApiResponses responses, HttpStatusCode statusCode, string resourceName) + { + OpenApiResponse response = GetOrAddResponse(responses, statusCode); + + response.Headers[HeaderNames.Location] = new OpenApiHeader + { + Description = $"The URL at which the newly created {resourceName} can be retrieved.", + Required = true, + Schema = new OpenApiSchema + { + Type = "string", + Format = "uri" + } + }; + } + + private static OpenApiResponse GetOrAddResponse(OpenApiResponses responses, HttpStatusCode statusCode) + { + string responseCode = ((int)statusCode).ToString(); + + if (!responses.TryGetValue(responseCode, out OpenApiResponse? response)) + { + response = new OpenApiResponse(); + responses.Add(responseCode, response); + } + + return response; + } + + private static void AddQueryStringParameters(OpenApiOperation operation, bool isRelationshipEndpoint) + { + // The JSON:API query string parameters (include, filter, sort, page[size], page[number], fields[]) are too dynamic to represent in OpenAPI. + // - The parameter names for fields[] require exploding to all resource types, because outcome of possible resource types depends on + // the relationship chains in include, which are provided at invocation time. + // - The parameter names for filter/sort take a relationship path, which could be infinite. For example: ?filter[node.parent.parent.parent...]=... + + // The next best thing is to expose the query string parameters as unstructured and optional. + // - This makes SwaggerUI ask for JSON, which is a bit odd, but it works. For example: {"sort":"-id"} produces: ?sort=-id + // - This makes NSwag produce a C# client with method signature: GetAsync(IDictionary? query) + // when combined with true in the project file. + + operation.Parameters.Add(new OpenApiParameter + { + In = ParameterLocation.Query, + Name = "query", + Schema = new OpenApiSchema + { + Type = "object", + AdditionalProperties = new OpenApiSchema + { + Type = "string", + Nullable = true + }, + // Prevent SwaggerUI from producing sample, which fails when used because unknown query string parameters are blocked by default. + Example = new OpenApiString(string.Empty) + }, + Description = isRelationshipEndpoint ? RelationshipQueryStringParameters : ResourceQueryStringParameters + }); + } + + private static void AddRequestHeaderIfNoneMatch(OpenApiOperation operation) + { + operation.Parameters.Add(new OpenApiParameter + { + In = ParameterLocation.Header, + Name = "If-None-Match", + Description = "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + Schema = new OpenApiSchema + { + Type = "string" + } + }); + } + + private static void ApplyPostOperations(OpenApiOperation operation) + { + SetOperationSummary(operation, "Performs multiple mutations in a linear and atomic manner."); + + SetRequestBodyDescription(operation.RequestBody, + "An array of mutation operations. For syntax, see the [Atomic Operations documentation](https://jsonapi.org/ext/atomic/)."); + + SetResponseDescription(operation.Responses, HttpStatusCode.OK, "All operations were successfully applied, which resulted in additional changes."); + + SetResponseDescription(operation.Responses, HttpStatusCode.NoContent, + "All operations were successfully applied, which did not result in additional changes."); + + SetResponseDescription(operation.Responses, HttpStatusCode.BadRequest, TextRequestBodyBad); + SetResponseDescription(operation.Responses, HttpStatusCode.Forbidden, "An operation is not accessible or a client-generated ID is used."); + SetResponseDescription(operation.Responses, HttpStatusCode.NotFound, "A resource or a related resource does not exist."); + SetResponseDescription(operation.Responses, HttpStatusCode.Conflict, TextConflict); + SetResponseDescription(operation.Responses, HttpStatusCode.UnprocessableEntity, TextRequestBodyValidationFailed); + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/EndpointOrderingFilter.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/EndpointOrderingFilter.cs new file mode 100644 index 0000000000..047ba4355a --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/EndpointOrderingFilter.cs @@ -0,0 +1,46 @@ +using System.Text.RegularExpressions; +using JetBrains.Annotations; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; + +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +internal sealed partial class EndpointOrderingFilter : IDocumentFilter +{ + public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) + { + ArgumentNullException.ThrowIfNull(swaggerDoc); + ArgumentNullException.ThrowIfNull(context); + + KeyValuePair[] endpointsInOrder = swaggerDoc.Paths.OrderBy(GetPrimaryResourcePublicName) + .ThenBy(GetRelationshipName).ThenBy(IsSecondaryEndpoint).ToArray(); + + swaggerDoc.Paths.Clear(); + + foreach ((string url, OpenApiPathItem path) in endpointsInOrder) + { + swaggerDoc.Paths.Add(url, path); + } + } + + private static string GetPrimaryResourcePublicName(KeyValuePair entry) + { + return entry.Value.Operations.First().Value.Tags.First().Name; + } + + private static bool IsSecondaryEndpoint(KeyValuePair entry) + { + return entry.Key.Contains("/relationships"); + } + + private static string GetRelationshipName(KeyValuePair entry) + { + Match match = RelationshipNameInUrlRegex().Match(entry.Key); + + return match.Success ? match.Groups["RelationshipName"].Value : string.Empty; + } + + [GeneratedRegex(@".*{id}/(?>relationships\/)?(?\w+)", RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture)] + private static partial Regex RelationshipNameInUrlRegex(); +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/JsonApiDataContractResolver.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/JsonApiDataContractResolver.cs new file mode 100644 index 0000000000..dcc652c696 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/JsonApiDataContractResolver.cs @@ -0,0 +1,99 @@ +using System.Reflection; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; + +/// +/// For schema generation, we rely on from Swashbuckle for all but our own JSON:API types. +/// +internal sealed class JsonApiDataContractResolver : ISerializerDataContractResolver +{ + private readonly IResourceGraph _resourceGraph; + private readonly JsonSerializerDataContractResolver _dataContractResolver; + + public JsonApiDataContractResolver(IJsonApiOptions options, IResourceGraph resourceGraph) + { + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(resourceGraph); + + _resourceGraph = resourceGraph; + _dataContractResolver = new JsonSerializerDataContractResolver(options.SerializerOptions); + } + + public DataContract GetDataContractForType(Type type) + { + ArgumentNullException.ThrowIfNull(type); + + if (type == typeof(IIdentifiable)) + { + // We have no way of telling Swashbuckle to opt out on this type, the closest we can get is return a contract with type Unknown. + return DataContract.ForDynamic(typeof(object)); + } + + DataContract dataContract = _dataContractResolver.GetDataContractForType(type); + + IList? replacementProperties = null; + + if (type.IsAssignableTo(typeof(IIdentifiable))) + { + replacementProperties = GetDataPropertiesThatExistInResourceClrType(type, dataContract); + } + + if (replacementProperties != null) + { + dataContract = ReplacePropertiesInDataContract(dataContract, replacementProperties); + } + + return dataContract; + } + + private static DataContract ReplacePropertiesInDataContract(DataContract dataContract, IEnumerable dataProperties) + { + return DataContract.ForObject(dataContract.UnderlyingType, dataProperties, dataContract.ObjectExtensionDataType, dataContract.ObjectTypeNameProperty, + dataContract.ObjectTypeNameValue); + } + + private List GetDataPropertiesThatExistInResourceClrType(Type resourceClrType, DataContract dataContract) + { + ResourceType resourceType = _resourceGraph.GetResourceType(resourceClrType); + List dataProperties = []; + + foreach (DataProperty property in dataContract.ObjectProperties) + { + if (property.MemberInfo.Name == nameof(Identifiable.Id)) + { + // Schemas of JsonApiDotNetCore resources will obtain an Id property through inheritance of a resource identifier type. + continue; + } + + ResourceFieldAttribute? matchingField = resourceType.Fields.SingleOrDefault(field => + IsPropertyCompatibleWithMember(field.Property, property.MemberInfo)); + + if (matchingField != null) + { + DataProperty matchingProperty = matchingField.PublicName != property.Name + ? ChangeDataPropertyName(property, matchingField.PublicName) + : property; + + dataProperties.Add(matchingProperty); + } + } + + return dataProperties; + } + + private static DataProperty ChangeDataPropertyName(DataProperty property, string name) + { + return new DataProperty(name, property.MemberType, property.IsRequired, property.IsNullable, property.IsReadOnly, property.IsWriteOnly, + property.MemberInfo); + } + + private static bool IsPropertyCompatibleWithMember(PropertyInfo property, MemberInfo member) + { + // In JsonApiDotNetCore the PropertyInfo for Id stored in AttrAttribute is that of the ReflectedType, whereas Newtonsoft uses the DeclaringType. + return property == member || property.DeclaringType?.GetProperty(property.Name) == member; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ResourceDocumentationReader.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ResourceDocumentationReader.cs new file mode 100644 index 0000000000..cd2727854c --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ResourceDocumentationReader.cs @@ -0,0 +1,89 @@ +using System.Collections.Concurrent; +using System.Reflection; +using System.Xml; +using System.Xml.XPath; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Resources.Annotations; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; + +internal sealed class ResourceDocumentationReader +{ + private static readonly ConcurrentDictionary NavigatorsByAssemblyPath = new(); + + public string? GetDocumentationForType(ResourceType resourceType) + { + ArgumentNullException.ThrowIfNull(resourceType); + + XPathNavigator? navigator = GetNavigator(resourceType.ClrType.Assembly); + + if (navigator != null) + { + string typeMemberName = XmlCommentsNodeNameHelper.GetMemberNameForType(resourceType.ClrType); + return GetSummary(navigator, typeMemberName); + } + + return null; + } + + public string? GetDocumentationForAttribute(AttrAttribute attribute) + { + ArgumentNullException.ThrowIfNull(attribute); + + XPathNavigator? navigator = GetNavigator(attribute.Type.ClrType.Assembly); + + if (navigator != null) + { + string propertyMemberName = XmlCommentsNodeNameHelper.GetMemberNameForFieldOrProperty(attribute.Property); + return GetSummary(navigator, propertyMemberName); + } + + return null; + } + + public string? GetDocumentationForRelationship(RelationshipAttribute relationship) + { + ArgumentNullException.ThrowIfNull(relationship); + + XPathNavigator? navigator = GetNavigator(relationship.Type.ClrType.Assembly); + + if (navigator != null) + { + string propertyMemberName = XmlCommentsNodeNameHelper.GetMemberNameForFieldOrProperty(relationship.Property); + return GetSummary(navigator, propertyMemberName); + } + + return null; + } + + private static XPathNavigator? GetNavigator(Assembly assembly) + { + string assemblyPath = assembly.Location; + + if (!string.IsNullOrEmpty(assemblyPath)) + { + return NavigatorsByAssemblyPath.GetOrAdd(assemblyPath, path => + { + string documentationPath = Path.ChangeExtension(path, ".xml"); + + if (File.Exists(documentationPath)) + { + using var reader = XmlReader.Create(documentationPath); + var document = new XPathDocument(reader); + return document.CreateNavigator(); + } + + return null; + }); + } + + return null; + } + + private string? GetSummary(XPathNavigator navigator, string memberName) + { + XPathNavigator? summaryNode = navigator.SelectSingleNode($"/doc/members/member[@name='{memberName}']/summary"); + return summaryNode != null ? XmlCommentsTextHelper.Humanize(summaryNode.InnerXml) : null; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ResourceFieldSchemaBuilder.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ResourceFieldSchemaBuilder.cs new file mode 100644 index 0000000000..31bf7be625 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ResourceFieldSchemaBuilder.cs @@ -0,0 +1,250 @@ +using System.Reflection; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; +using JsonApiDotNetCore.Resources.Annotations; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; + +internal sealed class ResourceFieldSchemaBuilder +{ + private readonly SchemaGenerationTracer _schemaGenerationTracer; + private readonly SchemaGenerator _defaultSchemaGenerator; + private readonly DataSchemaGenerator _dataSchemaGenerator; + private readonly LinksVisibilitySchemaGenerator _linksVisibilitySchemaGenerator; + private readonly ResourceSchemaType _resourceSchemaType; + private readonly ResourceFieldValidationMetadataProvider _resourceFieldValidationMetadataProvider; + private readonly RelationshipTypeFactory _relationshipTypeFactory; + + private readonly SchemaRepository _resourceSchemaRepository = new(); + private readonly ResourceDocumentationReader _resourceDocumentationReader = new(); + private readonly IDictionary _schemasForResourceFields; + + public ResourceFieldSchemaBuilder(SchemaGenerationTracer schemaGenerationTracer, SchemaGenerator defaultSchemaGenerator, + DataSchemaGenerator dataSchemaGenerator, LinksVisibilitySchemaGenerator linksVisibilitySchemaGenerator, + ResourceFieldValidationMetadataProvider resourceFieldValidationMetadataProvider, RelationshipTypeFactory relationshipTypeFactory, + ResourceSchemaType resourceSchemaType) + { + ArgumentNullException.ThrowIfNull(schemaGenerationTracer); + ArgumentNullException.ThrowIfNull(defaultSchemaGenerator); + ArgumentNullException.ThrowIfNull(dataSchemaGenerator); + ArgumentNullException.ThrowIfNull(linksVisibilitySchemaGenerator); + ArgumentNullException.ThrowIfNull(resourceSchemaType); + ArgumentNullException.ThrowIfNull(resourceFieldValidationMetadataProvider); + ArgumentNullException.ThrowIfNull(relationshipTypeFactory); + + _schemaGenerationTracer = schemaGenerationTracer; + _defaultSchemaGenerator = defaultSchemaGenerator; + _dataSchemaGenerator = dataSchemaGenerator; + _linksVisibilitySchemaGenerator = linksVisibilitySchemaGenerator; + _resourceSchemaType = resourceSchemaType; + _resourceFieldValidationMetadataProvider = resourceFieldValidationMetadataProvider; + _relationshipTypeFactory = relationshipTypeFactory; + + _schemasForResourceFields = GetFieldSchemas(); + } + + private IDictionary GetFieldSchemas() + { + if (!_resourceSchemaRepository.TryLookupByType(_resourceSchemaType.ResourceType.ClrType, out OpenApiSchema referenceSchemaForResource)) + { + referenceSchemaForResource = _defaultSchemaGenerator.GenerateSchema(_resourceSchemaType.ResourceType.ClrType, _resourceSchemaRepository); + } + + OpenApiSchema inlineSchemaForResource = _resourceSchemaRepository.Schemas[referenceSchemaForResource.Reference.Id].UnwrapLastExtendedSchema(); + return inlineSchemaForResource.Properties; + } + + public void SetMembersOfAttributes(OpenApiSchema fullSchemaForAttributes, bool forRequestSchema, SchemaRepository schemaRepository) + { + ArgumentNullException.ThrowIfNull(fullSchemaForAttributes); + ArgumentNullException.ThrowIfNull(schemaRepository); + AssertHasNoProperties(fullSchemaForAttributes); + + AttrCapabilities requiredCapability = GetRequiredCapabilityForAttributes(_resourceSchemaType.SchemaOpenType); + + foreach ((string publicName, OpenApiSchema schemaForResourceField) in _schemasForResourceFields) + { + AttrAttribute? matchingAttribute = _resourceSchemaType.ResourceType.FindAttributeByPublicName(publicName); + + if (matchingAttribute != null && matchingAttribute.Capabilities.HasFlag(requiredCapability)) + { + if (forRequestSchema) + { + if (matchingAttribute.Property.SetMethod == null) + { + continue; + } + } + else + { + if (matchingAttribute.Property.GetMethod == null) + { + continue; + } + } + + bool isInlineSchemaType = schemaForResourceField.AllOf.Count == 0; + + // Schemas for types like enum and complex attributes are handled as reference schemas. + if (!isInlineSchemaType) + { + OpenApiSchema referenceSchemaForAttribute = schemaForResourceField.UnwrapLastExtendedSchema(); + EnsureAttributeSchemaIsExposed(referenceSchemaForAttribute, matchingAttribute, schemaRepository); + } + + fullSchemaForAttributes.Properties.Add(matchingAttribute.PublicName, schemaForResourceField); + + schemaForResourceField.Nullable = _resourceFieldValidationMetadataProvider.IsNullable(matchingAttribute); + + if (IsFieldRequired(matchingAttribute)) + { + fullSchemaForAttributes.Required.Add(matchingAttribute.PublicName); + } + + schemaForResourceField.Description = _resourceDocumentationReader.GetDocumentationForAttribute(matchingAttribute); + } + } + } + + private static AttrCapabilities GetRequiredCapabilityForAttributes(Type resourceDataOpenType) + { + AttrCapabilities? capabilities = null; + + if (resourceDataOpenType == typeof(DataInResponse<>)) + { + capabilities = AttrCapabilities.AllowView; + } + else if (resourceDataOpenType == typeof(DataInCreateRequest<>)) + { + capabilities = AttrCapabilities.AllowCreate; + } + else if (resourceDataOpenType == typeof(DataInUpdateRequest<>)) + { + capabilities = AttrCapabilities.AllowChange; + } + + ConsistencyGuard.ThrowIf(capabilities == null); + return capabilities.Value; + } + + private void EnsureAttributeSchemaIsExposed(OpenApiSchema referenceSchemaForAttribute, AttrAttribute attribute, SchemaRepository schemaRepository) + { + Type nonNullableTypeInPropertyType = GetRepresentedTypeForAttributeSchema(attribute); + + if (schemaRepository.TryLookupByType(nonNullableTypeInPropertyType, out _)) + { + return; + } + + using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, nonNullableTypeInPropertyType); + + string schemaId = referenceSchemaForAttribute.Reference.Id; + OpenApiSchema fullSchema = _resourceSchemaRepository.Schemas[schemaId]; + + schemaRepository.AddDefinition(schemaId, fullSchema); + schemaRepository.RegisterType(nonNullableTypeInPropertyType, schemaId); + + traceScope.TraceSucceeded(schemaId); + } + + private Type GetRepresentedTypeForAttributeSchema(AttrAttribute attribute) + { + NullabilityInfoContext nullabilityInfoContext = new(); + NullabilityInfo attributeNullabilityInfo = nullabilityInfoContext.Create(attribute.Property); + + bool isNullable = attributeNullabilityInfo is { ReadState: NullabilityState.Nullable, WriteState: NullabilityState.Nullable }; + + Type nonNullableTypeInPropertyType = isNullable + ? Nullable.GetUnderlyingType(attribute.Property.PropertyType) ?? attribute.Property.PropertyType + : attribute.Property.PropertyType; + + return nonNullableTypeInPropertyType; + } + + private bool IsFieldRequired(ResourceFieldAttribute field) + { + bool isCreateResourceSchemaType = _resourceSchemaType.SchemaOpenType == typeof(DataInCreateRequest<>); + return isCreateResourceSchemaType && _resourceFieldValidationMetadataProvider.IsRequired(field); + } + + public void SetMembersOfRelationships(OpenApiSchema fullSchemaForRelationships, bool forRequestSchema, SchemaRepository schemaRepository) + { + ArgumentNullException.ThrowIfNull(fullSchemaForRelationships); + ArgumentNullException.ThrowIfNull(schemaRepository); + AssertHasNoProperties(fullSchemaForRelationships); + + foreach (string publicName in _schemasForResourceFields.Keys) + { + RelationshipAttribute? matchingRelationship = _resourceSchemaType.ResourceType.FindRelationshipByPublicName(publicName); + + if (matchingRelationship != null) + { + Type identifierSchemaOpenType = forRequestSchema ? typeof(IdentifierInRequest<>) : typeof(IdentifierInResponse<>); + Type identifierSchemaConstructedType = identifierSchemaOpenType.MakeGenericType(matchingRelationship.RightType.ClrType); + + _ = _dataSchemaGenerator.GenerateSchema(identifierSchemaConstructedType, forRequestSchema, schemaRepository); + AddRelationshipSchemaToResourceData(matchingRelationship, fullSchemaForRelationships, schemaRepository); + } + } + } + + private void AddRelationshipSchemaToResourceData(RelationshipAttribute relationship, OpenApiSchema fullSchemaForRelationships, + SchemaRepository schemaRepository) + { + Type relationshipSchemaType = GetRelationshipSchemaType(relationship, _resourceSchemaType.SchemaOpenType); + + OpenApiSchema referenceSchemaForRelationship = GetReferenceSchemaForRelationship(relationshipSchemaType, schemaRepository) ?? + CreateReferenceSchemaForRelationship(relationshipSchemaType, schemaRepository); + + OpenApiSchema extendedReferenceSchemaForRelationship = referenceSchemaForRelationship.WrapInExtendedSchema(); + extendedReferenceSchemaForRelationship.Description = _resourceDocumentationReader.GetDocumentationForRelationship(relationship); + + fullSchemaForRelationships.Properties.Add(relationship.PublicName, extendedReferenceSchemaForRelationship); + + if (IsFieldRequired(relationship)) + { + fullSchemaForRelationships.Required.Add(relationship.PublicName); + } + } + + private Type GetRelationshipSchemaType(RelationshipAttribute relationship, Type openSchemaType) + { + bool isResponseSchemaType = openSchemaType.IsAssignableTo(typeof(DataInResponse<>)); + return isResponseSchemaType ? _relationshipTypeFactory.GetForResponse(relationship) : _relationshipTypeFactory.GetForRequest(relationship); + } + + private OpenApiSchema? GetReferenceSchemaForRelationship(Type relationshipSchemaType, SchemaRepository schemaRepository) + { + return schemaRepository.TryLookupByType(relationshipSchemaType, out OpenApiSchema? referenceSchema) ? referenceSchema : null; + } + + private OpenApiSchema CreateReferenceSchemaForRelationship(Type relationshipSchemaType, SchemaRepository schemaRepository) + { + using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, relationshipSchemaType); + + OpenApiSchema referenceSchema = _defaultSchemaGenerator.GenerateSchema(relationshipSchemaType, schemaRepository); + + OpenApiSchema fullSchema = schemaRepository.Schemas[referenceSchema.Reference.Id]; + + if (JsonApiSchemaFacts.HasNullableDataProperty(relationshipSchemaType)) + { + fullSchema.Properties[JsonApiPropertyName.Data].Nullable = true; + } + + if (JsonApiSchemaFacts.IsRelationshipInResponseType(relationshipSchemaType)) + { + _linksVisibilitySchemaGenerator.UpdateSchemaForRelationship(relationshipSchemaType, fullSchema, schemaRepository); + } + + traceScope.TraceSucceeded(referenceSchema.Reference.Id); + return referenceSchema; + } + + private static void AssertHasNoProperties(OpenApiSchema fullSchema) + { + ConsistencyGuard.ThrowIf(fullSchema.Properties.Count > 0); + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ResourceSchemaType.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ResourceSchemaType.cs new file mode 100644 index 0000000000..148f0f4e2c --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ResourceSchemaType.cs @@ -0,0 +1,52 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.AtomicOperations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Relationships; +using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; + +/// +/// Represents a generic component schema type, whose first type parameter implements . Examples: +/// , , +/// , . +/// +internal sealed class ResourceSchemaType +{ + public Type SchemaConstructedType { get; } + public Type SchemaOpenType { get; } + public ResourceType ResourceType { get; } + + private ResourceSchemaType(Type schemaConstructedType, Type schemaOpenType, ResourceType resourceType) + { + SchemaConstructedType = schemaConstructedType; + SchemaOpenType = schemaOpenType; + ResourceType = resourceType; + } + + public static ResourceSchemaType Create(Type schemaConstructedType, IResourceGraph resourceGraph) + { + ArgumentNullException.ThrowIfNull(schemaConstructedType); + ArgumentNullException.ThrowIfNull(resourceGraph); + + Type schemaOpenType = schemaConstructedType.GetGenericTypeDefinition(); + Type resourceClrType = schemaConstructedType.GenericTypeArguments[0]; + ResourceType resourceType = resourceGraph.GetResourceType(resourceClrType); + + return new ResourceSchemaType(schemaConstructedType, schemaOpenType, resourceType); + } + + public ResourceSchemaType ChangeResourceType(ResourceType resourceType) + { + ArgumentNullException.ThrowIfNull(resourceType); + + Type schemaConstructedType = SchemaOpenType.MakeGenericType(resourceType.ClrType); + return new ResourceSchemaType(schemaConstructedType, SchemaOpenType, resourceType); + } + + public override string ToString() + { + return $"{SchemaOpenType.Name} for {ResourceType.ClrType.Name}"; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ServerDocumentFilter.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ServerDocumentFilter.cs new file mode 100644 index 0000000000..723499d39c --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ServerDocumentFilter.cs @@ -0,0 +1,32 @@ +using JetBrains.Annotations; +using Microsoft.AspNetCore.Http; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; + +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +internal sealed class ServerDocumentFilter : IDocumentFilter +{ + private readonly IHttpContextAccessor _httpContextAccessor; + + public ServerDocumentFilter(IHttpContextAccessor httpContextAccessor) + { + ArgumentNullException.ThrowIfNull(httpContextAccessor); + + _httpContextAccessor = httpContextAccessor; + } + + public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) + { + if (swaggerDoc.Servers.Count == 0 && _httpContextAccessor.HttpContext != null) + { + HttpRequest httpRequest = _httpContextAccessor.HttpContext.Request; + + swaggerDoc.Servers.Add(new OpenApiServer + { + Url = $"{httpRequest.Scheme}://{httpRequest.Host.Value}" + }); + } + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/StringEnumOrderingFilter.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/StringEnumOrderingFilter.cs new file mode 100644 index 0000000000..dec10db97b --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/StringEnumOrderingFilter.cs @@ -0,0 +1,54 @@ +using JetBrains.Annotations; +using Microsoft.OpenApi.Any; +using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Services; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; + +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +internal sealed class StringEnumOrderingFilter : IDocumentFilter +{ + internal const string RequiresSortKey = "x-requires-sort"; + + public void Apply(OpenApiDocument document, DocumentFilterContext context) + { + ArgumentNullException.ThrowIfNull(document); + ArgumentNullException.ThrowIfNull(context); + + var visitor = new OpenApiEnumVisitor(); + var walker = new OpenApiWalker(visitor); + walker.Walk(document); + } + + private sealed class OpenApiEnumVisitor : OpenApiVisitorBase + { + public override void Visit(OpenApiSchema schema) + { + if (HasSortAnnotation(schema)) + { + if (schema.Enum.Count > 1) + { + OrderEnumMembers(schema); + } + } + + schema.Extensions.Remove(RequiresSortKey); + } + + private static bool HasSortAnnotation(OpenApiSchema schema) + { + // Order our own enums, but don't touch enums from user-defined resource attributes. + return schema.Extensions.TryGetValue(RequiresSortKey, out IOpenApiExtension? extension) && extension is OpenApiBoolean { Value: true }; + } + + private static void OrderEnumMembers(OpenApiSchema schema) + { + List ordered = schema.Enum.OfType().OrderBy(openApiString => openApiString.Value).Cast().ToList(); + ConsistencyGuard.ThrowIf(ordered.Count != schema.Enum.Count); + + schema.Enum = ordered; + } + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/TypeExtensions.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/TypeExtensions.cs new file mode 100644 index 0000000000..ebfb000577 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/TypeExtensions.cs @@ -0,0 +1,11 @@ +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +internal static class TypeExtensions +{ + public static Type ConstructedToOpenType(this Type type) + { + ArgumentNullException.ThrowIfNull(type); + + return type.IsConstructedGenericType ? type.GetGenericTypeDefinition() : type; + } +} diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/UnusedComponentSchemaCleaner.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/UnusedComponentSchemaCleaner.cs new file mode 100644 index 0000000000..4e2addabb3 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/UnusedComponentSchemaCleaner.cs @@ -0,0 +1,185 @@ +using System.Diagnostics; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators; +using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Services; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace JsonApiDotNetCore.OpenApi.Swashbuckle; + +/// +/// Removes unreferenced component schemas from the OpenAPI document. +/// +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +internal sealed class UnusedComponentSchemaCleaner : IDocumentFilter +{ + private const string ComponentSchemaPrefix = "#/components/schemas/"; + + public void Apply(OpenApiDocument document, DocumentFilterContext context) + { + ArgumentNullException.ThrowIfNull(document); + ArgumentNullException.ThrowIfNull(context); + + document.Components.Schemas.Remove(GenerationCacheSchemaGenerator.SchemaId); + + HashSet unusedSchemaIds = GetUnusedSchemaIds(document); + AssertNoUnknownSchemasFound(unusedSchemaIds); + + RemoveUnusedComponentSchemas(document, unusedSchemaIds); + } + + private static HashSet GetUnusedSchemaIds(OpenApiDocument document) + { + HashSet reachableSchemaIds = ReachableRootsCollector.Instance.CollectReachableSchemaIds(document); + + ComponentSchemaUsageCollector collector = new(document); + return collector.CollectUnusedSchemaIds(reachableSchemaIds); + } + + [Conditional("DEBUG")] + private static void AssertNoUnknownSchemasFound(HashSet unusedSchemaIds) + { + if (unusedSchemaIds.Count > 0) + { + throw new InvalidOperationException($"Detected unused component schemas: {string.Join(", ", unusedSchemaIds)}"); + } + } + + private static void RemoveUnusedComponentSchemas(OpenApiDocument document, HashSet unusedSchemaIds) + { + foreach (string schemaId in unusedSchemaIds) + { + document.Components.Schemas.Remove(schemaId); + } + } + + private sealed class ReachableRootsCollector + { + public static ReachableRootsCollector Instance { get; } = new(); + + private ReachableRootsCollector() + { + } + + public HashSet CollectReachableSchemaIds(OpenApiDocument document) + { + ArgumentNullException.ThrowIfNull(document); + + var visitor = new ComponentSchemaReferenceVisitor(); + + var walker = new OpenApiWalker(visitor); + walker.Walk(document); + + return visitor.ReachableSchemaIds; + } + + private sealed class ComponentSchemaReferenceVisitor : OpenApiVisitorBase + { + public HashSet ReachableSchemaIds { get; } = []; + + public override void Visit(IOpenApiReferenceable referenceable) + { + if (!PathString.StartsWith(ComponentSchemaPrefix, StringComparison.Ordinal)) + { + if (referenceable is OpenApiSchema schema) + { + ReachableSchemaIds.Add(schema.Reference.Id); + } + } + } + } + } + + private sealed class ComponentSchemaUsageCollector + { + private readonly IDictionary _componentSchemas; + private readonly HashSet _schemaIdsInUse = []; + + public ComponentSchemaUsageCollector(OpenApiDocument document) + { + ArgumentNullException.ThrowIfNull(document); + + _componentSchemas = document.Components.Schemas; + } + + public HashSet CollectUnusedSchemaIds(ICollection reachableSchemaIds) + { + _schemaIdsInUse.Clear(); + + foreach (string schemaId in reachableSchemaIds) + { + WalkSchemaId(schemaId); + } + + HashSet unusedSchemaIds = _componentSchemas.Keys.ToHashSet(); + unusedSchemaIds.ExceptWith(_schemaIdsInUse); + return unusedSchemaIds; + } + + private void WalkSchemaId(string schemaId) + { + if (_schemaIdsInUse.Add(schemaId)) + { + if (_componentSchemas.TryGetValue(schemaId, out OpenApiSchema? schema)) + { + WalkSchema(schema); + } + } + } + + private void WalkSchema(OpenApiSchema? schema) + { + if (schema != null) + { + VisitSchema(schema); + + WalkSchema(schema.Items); + WalkSchema(schema.Not); + + foreach (OpenApiSchema? subSchema in schema.AllOf) + { + WalkSchema(subSchema); + } + + foreach (OpenApiSchema? subSchema in schema.AnyOf) + { + WalkSchema(subSchema); + } + + foreach (OpenApiSchema? subSchema in schema.OneOf) + { + WalkSchema(subSchema); + } + + foreach (OpenApiSchema? subSchema in schema.Properties.Values) + { + WalkSchema(subSchema); + } + + // ReSharper disable once TailRecursiveCall + WalkSchema(schema.AdditionalProperties); + } + } + + private void VisitSchema(OpenApiSchema schema) + { + if (schema.Reference is { Type: ReferenceType.Schema, IsExternal: false }) + { + WalkSchemaId(schema.Reference.Id); + } + + if (schema.Discriminator != null) + { + foreach (string mappingValue in schema.Discriminator.Mapping.Values) + { + if (mappingValue.StartsWith(ComponentSchemaPrefix, StringComparison.Ordinal)) + { + string schemaId = mappingValue[ComponentSchemaPrefix.Length..]; + WalkSchemaId(schemaId); + } + } + } + } + } +} diff --git a/src/JsonApiDotNetCore.SourceGenerators/JsonApiDotNetCore.SourceGenerators.csproj b/src/JsonApiDotNetCore.SourceGenerators/JsonApiDotNetCore.SourceGenerators.csproj index 5e1c03f6b7..8f9e397df3 100644 --- a/src/JsonApiDotNetCore.SourceGenerators/JsonApiDotNetCore.SourceGenerators.csproj +++ b/src/JsonApiDotNetCore.SourceGenerators/JsonApiDotNetCore.SourceGenerators.csproj @@ -11,7 +11,6 @@ - $(JsonApiDotNetCoreVersionPrefix) jsonapidotnetcore;jsonapi;json:api;dotnet;asp.net;rest;web-api Source generators for JsonApiDotNetCore, a framework for building JSON:API compliant REST APIs using ASP.NET and Entity Framework Core. json-api-dotnet diff --git a/src/JsonApiDotNetCore.SourceGenerators/SourceCodeWriter.cs b/src/JsonApiDotNetCore.SourceGenerators/SourceCodeWriter.cs index 1e68e5afab..3df1092c4b 100644 --- a/src/JsonApiDotNetCore.SourceGenerators/SourceCodeWriter.cs +++ b/src/JsonApiDotNetCore.SourceGenerators/SourceCodeWriter.cs @@ -10,36 +10,34 @@ internal sealed class SourceCodeWriter(GeneratorExecutionContext context, Diagno { private const int SpacesPerIndent = 4; - private static readonly IDictionary IndentTable = new Dictionary + private static readonly Dictionary IndentTable = new() { [0] = string.Empty, - [1] = new(' ', 1 * SpacesPerIndent), - [2] = new(' ', 2 * SpacesPerIndent), - [3] = new(' ', 3 * SpacesPerIndent) + [1] = new string(' ', 1 * SpacesPerIndent), + [2] = new string(' ', 2 * SpacesPerIndent), + [3] = new string(' ', 3 * SpacesPerIndent) }; - private static readonly IDictionary AggregateEndpointToServiceNameMap = - new Dictionary - { - [JsonApiEndpointsCopy.All] = ("IResourceService", "resourceService"), - [JsonApiEndpointsCopy.Query] = ("IResourceQueryService", "queryService"), - [JsonApiEndpointsCopy.Command] = ("IResourceCommandService", "commandService") - }; + private static readonly Dictionary AggregateEndpointToServiceNameMap = new() + { + [JsonApiEndpointsCopy.All] = ("IResourceService", "resourceService"), + [JsonApiEndpointsCopy.Query] = ("IResourceQueryService", "queryService"), + [JsonApiEndpointsCopy.Command] = ("IResourceCommandService", "commandService") + }; - private static readonly IDictionary EndpointToServiceNameMap = - new Dictionary - { - [JsonApiEndpointsCopy.GetCollection] = ("IGetAllService", "getAll"), - [JsonApiEndpointsCopy.GetSingle] = ("IGetByIdService", "getById"), - [JsonApiEndpointsCopy.GetSecondary] = ("IGetSecondaryService", "getSecondary"), - [JsonApiEndpointsCopy.GetRelationship] = ("IGetRelationshipService", "getRelationship"), - [JsonApiEndpointsCopy.Post] = ("ICreateService", "create"), - [JsonApiEndpointsCopy.PostRelationship] = ("IAddToRelationshipService", "addToRelationship"), - [JsonApiEndpointsCopy.Patch] = ("IUpdateService", "update"), - [JsonApiEndpointsCopy.PatchRelationship] = ("ISetRelationshipService", "setRelationship"), - [JsonApiEndpointsCopy.Delete] = ("IDeleteService", "delete"), - [JsonApiEndpointsCopy.DeleteRelationship] = ("IRemoveFromRelationshipService", "removeFromRelationship") - }; + private static readonly Dictionary EndpointToServiceNameMap = new() + { + [JsonApiEndpointsCopy.GetCollection] = ("IGetAllService", "getAll"), + [JsonApiEndpointsCopy.GetSingle] = ("IGetByIdService", "getById"), + [JsonApiEndpointsCopy.GetSecondary] = ("IGetSecondaryService", "getSecondary"), + [JsonApiEndpointsCopy.GetRelationship] = ("IGetRelationshipService", "getRelationship"), + [JsonApiEndpointsCopy.Post] = ("ICreateService", "create"), + [JsonApiEndpointsCopy.PostRelationship] = ("IAddToRelationshipService", "addToRelationship"), + [JsonApiEndpointsCopy.Patch] = ("IUpdateService", "update"), + [JsonApiEndpointsCopy.PatchRelationship] = ("ISetRelationshipService", "setRelationship"), + [JsonApiEndpointsCopy.Delete] = ("IDeleteService", "delete"), + [JsonApiEndpointsCopy.DeleteRelationship] = ("IRemoveFromRelationshipService", "removeFromRelationship") + }; private readonly GeneratorExecutionContext _context = context; private readonly DiagnosticDescriptor _missingIndentInTableErrorDescriptor = missingIndentInTableErrorDescriptor; diff --git a/src/JsonApiDotNetCore.SourceGenerators/TypeWithAttributeSyntaxReceiver.cs b/src/JsonApiDotNetCore.SourceGenerators/TypeWithAttributeSyntaxReceiver.cs index ad7b0d6ad5..17c5ffefd0 100644 --- a/src/JsonApiDotNetCore.SourceGenerators/TypeWithAttributeSyntaxReceiver.cs +++ b/src/JsonApiDotNetCore.SourceGenerators/TypeWithAttributeSyntaxReceiver.cs @@ -30,7 +30,7 @@ internal sealed class TypeWithAttributeSyntaxReceiver : ISyntaxReceiver public void OnVisitSyntaxNode(SyntaxNode syntaxNode) { - if (syntaxNode is TypeDeclarationSyntax typeDeclarationSyntax && typeDeclarationSyntax.AttributeLists.Any()) + if (syntaxNode is TypeDeclarationSyntax { AttributeLists.Count: > 0 } typeDeclarationSyntax) { TypeDeclarations.Add(typeDeclarationSyntax); } diff --git a/src/JsonApiDotNetCore/AtomicOperations/DefaultOperationFilter.cs b/src/JsonApiDotNetCore/AtomicOperations/DefaultOperationFilter.cs index d1ec1bd65c..fb632dd276 100644 --- a/src/JsonApiDotNetCore/AtomicOperations/DefaultOperationFilter.cs +++ b/src/JsonApiDotNetCore/AtomicOperations/DefaultOperationFilter.cs @@ -7,13 +7,37 @@ namespace JsonApiDotNetCore.AtomicOperations; /// -internal sealed class DefaultOperationFilter : IAtomicOperationFilter +public class DefaultOperationFilter : IAtomicOperationFilter { /// - public bool IsEnabled(ResourceType resourceType, WriteOperationKind writeOperation) + public virtual bool IsEnabled(ResourceType resourceType, WriteOperationKind writeOperation) { + ArgumentNullException.ThrowIfNull(resourceType); + + // To match the behavior of non-operations controllers: + // If an operation is enabled on a base type, it is implicitly enabled on all derived types. + ResourceType currentResourceType = resourceType; + + while (true) + { + JsonApiEndpoints? endpoints = GetJsonApiEndpoints(currentResourceType); + bool isEnabled = endpoints != null && Contains(endpoints.Value, writeOperation); + + if (isEnabled || currentResourceType.BaseType == null) + { + return isEnabled; + } + + currentResourceType = currentResourceType.BaseType; + } + } + + protected virtual JsonApiEndpoints? GetJsonApiEndpoints(ResourceType resourceType) + { + ArgumentNullException.ThrowIfNull(resourceType); + var resourceAttribute = resourceType.ClrType.GetCustomAttribute(); - return resourceAttribute != null && Contains(resourceAttribute.GenerateControllerEndpoints, writeOperation); + return resourceAttribute?.GenerateControllerEndpoints; } private static bool Contains(JsonApiEndpoints endpoints, WriteOperationKind writeOperation) diff --git a/src/JsonApiDotNetCore/AtomicOperations/EntityFrameworkCoreTransaction.cs b/src/JsonApiDotNetCore/AtomicOperations/EntityFrameworkCoreTransaction.cs index f59f86162d..d045bc0814 100644 --- a/src/JsonApiDotNetCore/AtomicOperations/EntityFrameworkCoreTransaction.cs +++ b/src/JsonApiDotNetCore/AtomicOperations/EntityFrameworkCoreTransaction.cs @@ -19,8 +19,8 @@ public sealed class EntityFrameworkCoreTransaction : IOperationsTransaction public EntityFrameworkCoreTransaction(IDbContextTransaction transaction, DbContext dbContext) { - ArgumentGuard.NotNull(transaction); - ArgumentGuard.NotNull(dbContext); + ArgumentNullException.ThrowIfNull(transaction); + ArgumentNullException.ThrowIfNull(dbContext); _transaction = transaction; _dbContext = dbContext; diff --git a/src/JsonApiDotNetCore/AtomicOperations/EntityFrameworkCoreTransactionFactory.cs b/src/JsonApiDotNetCore/AtomicOperations/EntityFrameworkCoreTransactionFactory.cs index 8ef44cb627..2fe6959b1f 100644 --- a/src/JsonApiDotNetCore/AtomicOperations/EntityFrameworkCoreTransactionFactory.cs +++ b/src/JsonApiDotNetCore/AtomicOperations/EntityFrameworkCoreTransactionFactory.cs @@ -15,8 +15,8 @@ public sealed class EntityFrameworkCoreTransactionFactory : IOperationsTransacti public EntityFrameworkCoreTransactionFactory(IDbContextResolver dbContextResolver, IJsonApiOptions options) { - ArgumentGuard.NotNull(dbContextResolver); - ArgumentGuard.NotNull(options); + ArgumentNullException.ThrowIfNull(dbContextResolver); + ArgumentNullException.ThrowIfNull(options); _dbContextResolver = dbContextResolver; _options = options; diff --git a/src/JsonApiDotNetCore/AtomicOperations/IAtomicOperationFilter.cs b/src/JsonApiDotNetCore/AtomicOperations/IAtomicOperationFilter.cs index 240efbf936..47d534c5b5 100644 --- a/src/JsonApiDotNetCore/AtomicOperations/IAtomicOperationFilter.cs +++ b/src/JsonApiDotNetCore/AtomicOperations/IAtomicOperationFilter.cs @@ -6,7 +6,7 @@ namespace JsonApiDotNetCore.AtomicOperations; /// -/// Determines whether an operation in an atomic:operations request can be used. +/// Determines whether an operation in an atomic:operations request can be used. For non-operations requests, see . /// /// /// The default implementation relies on the usage of . If you're using explicit diff --git a/src/JsonApiDotNetCore/AtomicOperations/LocalIdTracker.cs b/src/JsonApiDotNetCore/AtomicOperations/LocalIdTracker.cs index 09ebefaf93..bb058475e3 100644 --- a/src/JsonApiDotNetCore/AtomicOperations/LocalIdTracker.cs +++ b/src/JsonApiDotNetCore/AtomicOperations/LocalIdTracker.cs @@ -6,7 +6,7 @@ namespace JsonApiDotNetCore.AtomicOperations; /// public sealed class LocalIdTracker : ILocalIdTracker { - private readonly IDictionary _idsTracked = new Dictionary(); + private readonly Dictionary _idsTracked = new(); /// public void Reset() @@ -17,8 +17,8 @@ public void Reset() /// public void Declare(string localId, ResourceType resourceType) { - ArgumentGuard.NotNullNorEmpty(localId); - ArgumentGuard.NotNull(resourceType); + ArgumentException.ThrowIfNullOrEmpty(localId); + ArgumentNullException.ThrowIfNull(resourceType); AssertIsNotDeclared(localId); @@ -36,9 +36,9 @@ private void AssertIsNotDeclared(string localId) /// public void Assign(string localId, ResourceType resourceType, string stringId) { - ArgumentGuard.NotNullNorEmpty(localId); - ArgumentGuard.NotNull(resourceType); - ArgumentGuard.NotNullNorEmpty(stringId); + ArgumentException.ThrowIfNullOrEmpty(localId); + ArgumentNullException.ThrowIfNull(resourceType); + ArgumentException.ThrowIfNullOrEmpty(stringId); AssertIsDeclared(localId); @@ -57,8 +57,8 @@ public void Assign(string localId, ResourceType resourceType, string stringId) /// public string GetValue(string localId, ResourceType resourceType) { - ArgumentGuard.NotNullNorEmpty(localId); - ArgumentGuard.NotNull(resourceType); + ArgumentException.ThrowIfNullOrEmpty(localId); + ArgumentNullException.ThrowIfNull(resourceType); AssertIsDeclared(localId); diff --git a/src/JsonApiDotNetCore/AtomicOperations/LocalIdValidator.cs b/src/JsonApiDotNetCore/AtomicOperations/LocalIdValidator.cs index fb75fe3c7f..92d9bd8319 100644 --- a/src/JsonApiDotNetCore/AtomicOperations/LocalIdValidator.cs +++ b/src/JsonApiDotNetCore/AtomicOperations/LocalIdValidator.cs @@ -18,8 +18,8 @@ public sealed class LocalIdValidator public LocalIdValidator(ILocalIdTracker localIdTracker, IResourceGraph resourceGraph) { - ArgumentGuard.NotNull(localIdTracker); - ArgumentGuard.NotNull(resourceGraph); + ArgumentNullException.ThrowIfNull(localIdTracker); + ArgumentNullException.ThrowIfNull(resourceGraph); _localIdTracker = localIdTracker; _resourceGraph = resourceGraph; @@ -27,7 +27,7 @@ public LocalIdValidator(ILocalIdTracker localIdTracker, IResourceGraph resourceG public void Validate(IEnumerable operations) { - ArgumentGuard.NotNull(operations); + ArgumentNullException.ThrowIfNull(operations); _localIdTracker.Reset(); diff --git a/src/JsonApiDotNetCore/AtomicOperations/OperationProcessorAccessor.cs b/src/JsonApiDotNetCore/AtomicOperations/OperationProcessorAccessor.cs index 28ac16d612..a6dc2051ec 100644 --- a/src/JsonApiDotNetCore/AtomicOperations/OperationProcessorAccessor.cs +++ b/src/JsonApiDotNetCore/AtomicOperations/OperationProcessorAccessor.cs @@ -15,7 +15,7 @@ public class OperationProcessorAccessor : IOperationProcessorAccessor public OperationProcessorAccessor(IServiceProvider serviceProvider) { - ArgumentGuard.NotNull(serviceProvider); + ArgumentNullException.ThrowIfNull(serviceProvider); _serviceProvider = serviceProvider; } @@ -23,7 +23,7 @@ public OperationProcessorAccessor(IServiceProvider serviceProvider) /// public Task ProcessAsync(OperationContainer operation, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(operation); + ArgumentNullException.ThrowIfNull(operation); IOperationProcessor processor = ResolveProcessor(operation); return processor.ProcessAsync(operation, cancellationToken); @@ -31,6 +31,8 @@ public OperationProcessorAccessor(IServiceProvider serviceProvider) protected virtual IOperationProcessor ResolveProcessor(OperationContainer operation) { + ArgumentNullException.ThrowIfNull(operation); + Type processorInterface = GetProcessorInterface(operation.Request.WriteOperation!.Value); ResourceType resourceType = operation.Request.PrimaryResourceType!; diff --git a/src/JsonApiDotNetCore/AtomicOperations/OperationsProcessor.cs b/src/JsonApiDotNetCore/AtomicOperations/OperationsProcessor.cs index cf1cdd7b65..f3d0b22256 100644 --- a/src/JsonApiDotNetCore/AtomicOperations/OperationsProcessor.cs +++ b/src/JsonApiDotNetCore/AtomicOperations/OperationsProcessor.cs @@ -25,13 +25,13 @@ public OperationsProcessor(IOperationProcessorAccessor operationProcessorAccesso ILocalIdTracker localIdTracker, IResourceGraph resourceGraph, IJsonApiRequest request, ITargetedFields targetedFields, ISparseFieldSetCache sparseFieldSetCache) { - ArgumentGuard.NotNull(operationProcessorAccessor); - ArgumentGuard.NotNull(operationsTransactionFactory); - ArgumentGuard.NotNull(localIdTracker); - ArgumentGuard.NotNull(resourceGraph); - ArgumentGuard.NotNull(request); - ArgumentGuard.NotNull(targetedFields); - ArgumentGuard.NotNull(sparseFieldSetCache); + ArgumentNullException.ThrowIfNull(operationProcessorAccessor); + ArgumentNullException.ThrowIfNull(operationsTransactionFactory); + ArgumentNullException.ThrowIfNull(localIdTracker); + ArgumentNullException.ThrowIfNull(resourceGraph); + ArgumentNullException.ThrowIfNull(request); + ArgumentNullException.ThrowIfNull(targetedFields); + ArgumentNullException.ThrowIfNull(sparseFieldSetCache); _operationProcessorAccessor = operationProcessorAccessor; _operationsTransactionFactory = operationsTransactionFactory; @@ -46,12 +46,12 @@ public OperationsProcessor(IOperationProcessorAccessor operationProcessorAccesso /// public virtual async Task> ProcessAsync(IList operations, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(operations); + ArgumentNullException.ThrowIfNull(operations); _localIdValidator.Validate(operations); _localIdTracker.Reset(); - var results = new List(); + List results = []; await using IOperationsTransaction transaction = await _operationsTransactionFactory.BeginTransactionAsync(cancellationToken); @@ -101,6 +101,8 @@ public OperationsProcessor(IOperationProcessorAccessor operationProcessorAccesso protected virtual async Task ProcessOperationAsync(OperationContainer operation, CancellationToken cancellationToken) { + ArgumentNullException.ThrowIfNull(operation); + cancellationToken.ThrowIfCancellationRequested(); TrackLocalIdsForOperation(operation); @@ -113,6 +115,8 @@ public OperationsProcessor(IOperationProcessorAccessor operationProcessorAccesso protected void TrackLocalIdsForOperation(OperationContainer operation) { + ArgumentNullException.ThrowIfNull(operation); + if (operation.Request.WriteOperation == WriteOperationKind.CreateResource) { DeclareLocalId(operation.Resource, operation.Request.PrimaryResourceType!); diff --git a/src/JsonApiDotNetCore/AtomicOperations/Processors/AddToRelationshipProcessor.cs b/src/JsonApiDotNetCore/AtomicOperations/Processors/AddToRelationshipProcessor.cs index fa835910ef..e84756120a 100644 --- a/src/JsonApiDotNetCore/AtomicOperations/Processors/AddToRelationshipProcessor.cs +++ b/src/JsonApiDotNetCore/AtomicOperations/Processors/AddToRelationshipProcessor.cs @@ -13,7 +13,7 @@ public class AddToRelationshipProcessor : IAddToRelationshipProc public AddToRelationshipProcessor(IAddToRelationshipService service) { - ArgumentGuard.NotNull(service); + ArgumentNullException.ThrowIfNull(service); _service = service; } @@ -21,7 +21,7 @@ public AddToRelationshipProcessor(IAddToRelationshipService serv /// public virtual async Task ProcessAsync(OperationContainer operation, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(operation); + ArgumentNullException.ThrowIfNull(operation); var leftId = (TId)operation.Resource.GetTypedId(); ISet rightResourceIds = operation.GetSecondaryResources(); diff --git a/src/JsonApiDotNetCore/AtomicOperations/Processors/CreateProcessor.cs b/src/JsonApiDotNetCore/AtomicOperations/Processors/CreateProcessor.cs index e4ccd7b69d..c7bf3c9b77 100644 --- a/src/JsonApiDotNetCore/AtomicOperations/Processors/CreateProcessor.cs +++ b/src/JsonApiDotNetCore/AtomicOperations/Processors/CreateProcessor.cs @@ -14,8 +14,8 @@ public class CreateProcessor : ICreateProcessor public CreateProcessor(ICreateService service, ILocalIdTracker localIdTracker) { - ArgumentGuard.NotNull(service); - ArgumentGuard.NotNull(localIdTracker); + ArgumentNullException.ThrowIfNull(service); + ArgumentNullException.ThrowIfNull(localIdTracker); _service = service; _localIdTracker = localIdTracker; @@ -24,7 +24,7 @@ public CreateProcessor(ICreateService service, ILocalIdTracker l /// public virtual async Task ProcessAsync(OperationContainer operation, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(operation); + ArgumentNullException.ThrowIfNull(operation); TResource? newResource = await _service.CreateAsync((TResource)operation.Resource, cancellationToken); diff --git a/src/JsonApiDotNetCore/AtomicOperations/Processors/DeleteProcessor.cs b/src/JsonApiDotNetCore/AtomicOperations/Processors/DeleteProcessor.cs index d758e065bc..5709188a8c 100644 --- a/src/JsonApiDotNetCore/AtomicOperations/Processors/DeleteProcessor.cs +++ b/src/JsonApiDotNetCore/AtomicOperations/Processors/DeleteProcessor.cs @@ -13,7 +13,7 @@ public class DeleteProcessor : IDeleteProcessor public DeleteProcessor(IDeleteService service) { - ArgumentGuard.NotNull(service); + ArgumentNullException.ThrowIfNull(service); _service = service; } @@ -21,7 +21,7 @@ public DeleteProcessor(IDeleteService service) /// public virtual async Task ProcessAsync(OperationContainer operation, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(operation); + ArgumentNullException.ThrowIfNull(operation); var id = (TId)operation.Resource.GetTypedId(); await _service.DeleteAsync(id!, cancellationToken); diff --git a/src/JsonApiDotNetCore/AtomicOperations/Processors/RemoveFromRelationshipProcessor.cs b/src/JsonApiDotNetCore/AtomicOperations/Processors/RemoveFromRelationshipProcessor.cs index 6222a01fd8..81c4eb93ee 100644 --- a/src/JsonApiDotNetCore/AtomicOperations/Processors/RemoveFromRelationshipProcessor.cs +++ b/src/JsonApiDotNetCore/AtomicOperations/Processors/RemoveFromRelationshipProcessor.cs @@ -13,7 +13,7 @@ public class RemoveFromRelationshipProcessor : IRemoveFromRelati public RemoveFromRelationshipProcessor(IRemoveFromRelationshipService service) { - ArgumentGuard.NotNull(service); + ArgumentNullException.ThrowIfNull(service); _service = service; } @@ -21,7 +21,7 @@ public RemoveFromRelationshipProcessor(IRemoveFromRelationshipService public virtual async Task ProcessAsync(OperationContainer operation, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(operation); + ArgumentNullException.ThrowIfNull(operation); var leftId = (TId)operation.Resource.GetTypedId(); ISet rightResourceIds = operation.GetSecondaryResources(); diff --git a/src/JsonApiDotNetCore/AtomicOperations/Processors/SetRelationshipProcessor.cs b/src/JsonApiDotNetCore/AtomicOperations/Processors/SetRelationshipProcessor.cs index 3eeaa77fb3..913068a26c 100644 --- a/src/JsonApiDotNetCore/AtomicOperations/Processors/SetRelationshipProcessor.cs +++ b/src/JsonApiDotNetCore/AtomicOperations/Processors/SetRelationshipProcessor.cs @@ -10,12 +10,11 @@ namespace JsonApiDotNetCore.AtomicOperations.Processors; public class SetRelationshipProcessor : ISetRelationshipProcessor where TResource : class, IIdentifiable { - private readonly CollectionConverter _collectionConverter = new(); private readonly ISetRelationshipService _service; public SetRelationshipProcessor(ISetRelationshipService service) { - ArgumentGuard.NotNull(service); + ArgumentNullException.ThrowIfNull(service); _service = service; } @@ -23,7 +22,7 @@ public SetRelationshipProcessor(ISetRelationshipService service) /// public virtual async Task ProcessAsync(OperationContainer operation, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(operation); + ArgumentNullException.ThrowIfNull(operation); var leftId = (TId)operation.Resource.GetTypedId(); object? rightValue = GetRelationshipRightValue(operation); @@ -40,7 +39,7 @@ public SetRelationshipProcessor(ISetRelationshipService service) if (relationship is HasManyAttribute) { - IReadOnlyCollection rightResources = _collectionConverter.ExtractResources(rightValue); + IReadOnlyCollection rightResources = CollectionConverter.Instance.ExtractResources(rightValue); return rightResources.ToHashSet(IdentifiableComparer.Instance); } diff --git a/src/JsonApiDotNetCore/AtomicOperations/Processors/UpdateProcessor.cs b/src/JsonApiDotNetCore/AtomicOperations/Processors/UpdateProcessor.cs index 32fe2a1eb5..cf66c70462 100644 --- a/src/JsonApiDotNetCore/AtomicOperations/Processors/UpdateProcessor.cs +++ b/src/JsonApiDotNetCore/AtomicOperations/Processors/UpdateProcessor.cs @@ -13,7 +13,7 @@ public class UpdateProcessor : IUpdateProcessor public UpdateProcessor(IUpdateService service) { - ArgumentGuard.NotNull(service); + ArgumentNullException.ThrowIfNull(service); _service = service; } @@ -21,7 +21,7 @@ public UpdateProcessor(IUpdateService service) /// public virtual async Task ProcessAsync(OperationContainer operation, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(operation); + ArgumentNullException.ThrowIfNull(operation); var resource = (TResource)operation.Resource; TResource? updated = await _service.UpdateAsync(resource.Id!, resource, cancellationToken); diff --git a/src/JsonApiDotNetCore/AtomicOperations/RevertRequestStateOnDispose.cs b/src/JsonApiDotNetCore/AtomicOperations/RevertRequestStateOnDispose.cs index 1951333d0c..82b0641c34 100644 --- a/src/JsonApiDotNetCore/AtomicOperations/RevertRequestStateOnDispose.cs +++ b/src/JsonApiDotNetCore/AtomicOperations/RevertRequestStateOnDispose.cs @@ -11,12 +11,12 @@ internal sealed class RevertRequestStateOnDispose : IDisposable private readonly IJsonApiRequest _sourceRequest; private readonly ITargetedFields? _sourceTargetedFields; - private readonly IJsonApiRequest _backupRequest = new JsonApiRequest(); - private readonly ITargetedFields _backupTargetedFields = new TargetedFields(); + private readonly JsonApiRequest _backupRequest = new(); + private readonly TargetedFields _backupTargetedFields = new(); public RevertRequestStateOnDispose(IJsonApiRequest request, ITargetedFields? targetedFields) { - ArgumentGuard.NotNull(request); + ArgumentNullException.ThrowIfNull(request); _sourceRequest = request; _backupRequest.CopyFrom(request); diff --git a/src/JsonApiDotNetCore/CollectionExtensions.cs b/src/JsonApiDotNetCore/CollectionExtensions.cs index 4e02b60fc5..ca46953bfc 100644 --- a/src/JsonApiDotNetCore/CollectionExtensions.cs +++ b/src/JsonApiDotNetCore/CollectionExtensions.cs @@ -16,10 +16,25 @@ public static bool IsNullOrEmpty([NotNullWhen(false)] this IEnumerable? so return !source.Any(); } + public static int FindIndex(this IReadOnlyList source, T item) + { + ArgumentNullException.ThrowIfNull(source); + + for (int index = 0; index < source.Count; index++) + { + if (EqualityComparer.Default.Equals(source[index], item)) + { + return index; + } + } + + return -1; + } + public static int FindIndex(this IReadOnlyList source, Predicate match) { - ArgumentGuard.NotNull(source); - ArgumentGuard.NotNull(match); + ArgumentNullException.ThrowIfNull(source); + ArgumentNullException.ThrowIfNull(match); for (int index = 0; index < source.Count; index++) { @@ -82,7 +97,7 @@ public static bool DictionaryEqual(this IReadOnlyDictionary EmptyIfNull(this IEnumerable? source) { - return source ?? []; + return source ?? Array.Empty(); } public static IEnumerable WhereNotNull(this IEnumerable source) diff --git a/src/JsonApiDotNetCore/Configuration/ApplicationBuilderExtensions.cs b/src/JsonApiDotNetCore/Configuration/ApplicationBuilderExtensions.cs index 8ed4e42a42..3957a28835 100644 --- a/src/JsonApiDotNetCore/Configuration/ApplicationBuilderExtensions.cs +++ b/src/JsonApiDotNetCore/Configuration/ApplicationBuilderExtensions.cs @@ -1,6 +1,7 @@ using JsonApiDotNetCore.Middleware; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; namespace JsonApiDotNetCore.Configuration; @@ -22,7 +23,8 @@ public static class ApplicationBuilderExtensions /// public static void UseJsonApi(this IApplicationBuilder builder) { - ArgumentGuard.NotNull(builder); + ArgumentNullException.ThrowIfNull(builder); + AssertAspNetCoreOpenApiIsNotRegistered(builder.ApplicationServices); using (IServiceScope scope = builder.ApplicationServices.CreateScope()) { @@ -46,4 +48,33 @@ public static void UseJsonApi(this IApplicationBuilder builder) builder.UseMiddleware(); } + + private static void AssertAspNetCoreOpenApiIsNotRegistered(IServiceProvider serviceProvider) + { + Type? optionsType = TryLoadOptionsType(); + + if (optionsType != null) + { + Type configureType = typeof(IConfigureOptions<>).MakeGenericType(optionsType); + object? configureInstance = serviceProvider.GetService(configureType); + + if (configureInstance != null) + { + throw new InvalidOperationException("JsonApiDotNetCore is incompatible with ASP.NET OpenAPI. " + + "Replace 'services.AddOpenApi()' with 'services.AddOpenApiForJsonApi()' from the JsonApiDotNetCore.OpenApi.Swashbuckle NuGet package."); + } + } + } + + private static Type? TryLoadOptionsType() + { + try + { + return Type.GetType("Microsoft.AspNetCore.OpenApi.OpenApiOptions, Microsoft.AspNetCore.OpenApi"); + } + catch (FileLoadException) + { + return null; + } + } } diff --git a/src/JsonApiDotNetCore/Configuration/DefaultJsonApiApplicationBuilderEvents.cs b/src/JsonApiDotNetCore/Configuration/DefaultJsonApiApplicationBuilderEvents.cs new file mode 100644 index 0000000000..c1bea78418 --- /dev/null +++ b/src/JsonApiDotNetCore/Configuration/DefaultJsonApiApplicationBuilderEvents.cs @@ -0,0 +1,20 @@ +using JsonApiDotNetCore.Serialization.JsonConverters; + +namespace JsonApiDotNetCore.Configuration; + +internal sealed class DefaultJsonApiApplicationBuilderEvents : IJsonApiApplicationBuilderEvents +{ + private readonly IJsonApiOptions _options; + + public DefaultJsonApiApplicationBuilderEvents(IJsonApiOptions options) + { + ArgumentNullException.ThrowIfNull(options); + + _options = options; + } + + public void ResourceGraphBuilt(IResourceGraph resourceGraph) + { + _options.SerializerOptions.Converters.Add(new ResourceObjectConverter(resourceGraph)); + } +} diff --git a/src/JsonApiDotNetCore/Configuration/IJsonApiApplicationBuilderEvents.cs b/src/JsonApiDotNetCore/Configuration/IJsonApiApplicationBuilderEvents.cs new file mode 100644 index 0000000000..525240bfc2 --- /dev/null +++ b/src/JsonApiDotNetCore/Configuration/IJsonApiApplicationBuilderEvents.cs @@ -0,0 +1,6 @@ +namespace JsonApiDotNetCore.Configuration; + +internal interface IJsonApiApplicationBuilderEvents +{ + void ResourceGraphBuilt(IResourceGraph resourceGraph); +} diff --git a/src/JsonApiDotNetCore/Configuration/IJsonApiOptions.cs b/src/JsonApiDotNetCore/Configuration/IJsonApiOptions.cs index b5c03a05a5..7141125e40 100644 --- a/src/JsonApiDotNetCore/Configuration/IJsonApiOptions.cs +++ b/src/JsonApiDotNetCore/Configuration/IJsonApiOptions.cs @@ -1,6 +1,8 @@ using System.Data; using System.Text.Json; using JetBrains.Annotations; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; using JsonApiDotNetCore.Resources.Annotations; using JsonApiDotNetCore.Serialization.Objects; @@ -172,6 +174,18 @@ public interface IJsonApiOptions /// IsolationLevel? TransactionIsolationLevel { get; } + /// + /// Lists the JSON:API extensions that are turned on. Empty by default, but if your project contains a controller that derives from + /// , the and + /// extensions are automatically added. + /// + /// + /// To implement a custom JSON:API extension, add it here and override to indicate which + /// combinations of extensions are available, depending on the current endpoint. Use to obtain the active + /// extensions when implementing extension-specific logic. + /// + IReadOnlySet Extensions { get; } + /// /// Enables to customize the settings that are used by the . /// diff --git a/src/JsonApiDotNetCore/Configuration/IResourceGraph.cs b/src/JsonApiDotNetCore/Configuration/IResourceGraph.cs index a98b74c3fe..a2c4f3283c 100644 --- a/src/JsonApiDotNetCore/Configuration/IResourceGraph.cs +++ b/src/JsonApiDotNetCore/Configuration/IResourceGraph.cs @@ -65,7 +65,7 @@ IReadOnlyCollection GetFields(Expression /// /// Should be of the form: new { resource.attribute1, resource.Attribute2 } + /// (TResource resource) => new { resource.Attribute1, resource.Attribute2 } /// ]]> /// IReadOnlyCollection GetAttributes(Expression> selector) diff --git a/src/JsonApiDotNetCore/Configuration/InjectablesAssemblyScanner.cs b/src/JsonApiDotNetCore/Configuration/InjectablesAssemblyScanner.cs index 9985533776..3ac71053b0 100644 --- a/src/JsonApiDotNetCore/Configuration/InjectablesAssemblyScanner.cs +++ b/src/JsonApiDotNetCore/Configuration/InjectablesAssemblyScanner.cs @@ -46,8 +46,8 @@ internal sealed class InjectablesAssemblyScanner public InjectablesAssemblyScanner(ResourceDescriptorAssemblyCache assemblyCache, IServiceCollection services) { - ArgumentGuard.NotNull(assemblyCache); - ArgumentGuard.NotNull(services); + ArgumentNullException.ThrowIfNull(assemblyCache); + ArgumentNullException.ThrowIfNull(services); _assemblyCache = assemblyCache; _services = services; diff --git a/src/JsonApiDotNetCore/Configuration/InverseNavigationResolver.cs b/src/JsonApiDotNetCore/Configuration/InverseNavigationResolver.cs index 6e3e2d718c..4527afdcbe 100644 --- a/src/JsonApiDotNetCore/Configuration/InverseNavigationResolver.cs +++ b/src/JsonApiDotNetCore/Configuration/InverseNavigationResolver.cs @@ -11,15 +11,15 @@ namespace JsonApiDotNetCore.Configuration; public sealed class InverseNavigationResolver : IInverseNavigationResolver { private readonly IResourceGraph _resourceGraph; - private readonly IEnumerable _dbContextResolvers; + private readonly IDbContextResolver[] _dbContextResolvers; public InverseNavigationResolver(IResourceGraph resourceGraph, IEnumerable dbContextResolvers) { - ArgumentGuard.NotNull(resourceGraph); - ArgumentGuard.NotNull(dbContextResolvers); + ArgumentNullException.ThrowIfNull(resourceGraph); + ArgumentNullException.ThrowIfNull(dbContextResolvers); _resourceGraph = resourceGraph; - _dbContextResolvers = dbContextResolvers; + _dbContextResolvers = dbContextResolvers as IDbContextResolver[] ?? dbContextResolvers.ToArray(); } /// @@ -34,19 +34,19 @@ public void Resolve() private void Resolve(DbContext dbContext) { - foreach (ResourceType resourceType in _resourceGraph.GetResourceTypes().Where(resourceType => resourceType.Relationships.Any())) + foreach (ResourceType resourceType in _resourceGraph.GetResourceTypes().Where(resourceType => resourceType.Relationships.Count > 0)) { IEntityType? entityType = dbContext.Model.FindEntityType(resourceType.ClrType); if (entityType != null) { - IDictionary navigationMap = GetNavigations(entityType); + Dictionary navigationMap = GetNavigations(entityType); ResolveRelationships(resourceType.Relationships, navigationMap); } } } - private static IDictionary GetNavigations(IEntityType entityType) + private static Dictionary GetNavigations(IEntityType entityType) { // @formatter:wrap_chained_method_calls chop_always @@ -58,7 +58,7 @@ private static IDictionary GetNavigations(IEntityType e // @formatter:wrap_chained_method_calls restore } - private void ResolveRelationships(IReadOnlyCollection relationships, IDictionary navigationMap) + private void ResolveRelationships(IReadOnlyCollection relationships, Dictionary navigationMap) { foreach (RelationshipAttribute relationship in relationships) { diff --git a/src/JsonApiDotNetCore/Configuration/JsonApiApplicationBuilder.cs b/src/JsonApiDotNetCore/Configuration/JsonApiApplicationBuilder.cs index 2f725e8c68..65646b7697 100644 --- a/src/JsonApiDotNetCore/Configuration/JsonApiApplicationBuilder.cs +++ b/src/JsonApiDotNetCore/Configuration/JsonApiApplicationBuilder.cs @@ -7,7 +7,6 @@ using JsonApiDotNetCore.QueryStrings; using JsonApiDotNetCore.Repositories; using JsonApiDotNetCore.Resources; -using JsonApiDotNetCore.Serialization.JsonConverters; using JsonApiDotNetCore.Serialization.Request; using JsonApiDotNetCore.Serialization.Request.Adapters; using JsonApiDotNetCore.Serialization.Response; @@ -37,8 +36,8 @@ internal sealed class JsonApiApplicationBuilder : IJsonApiApplicationBuilder public JsonApiApplicationBuilder(IServiceCollection services, IMvcCoreBuilder mvcBuilder) { - ArgumentGuard.NotNull(services); - ArgumentGuard.NotNull(mvcBuilder); + ArgumentNullException.ThrowIfNull(services); + ArgumentNullException.ThrowIfNull(mvcBuilder); _services = services; _mvcBuilder = mvcBuilder; @@ -69,11 +68,13 @@ public void ConfigureAutoDiscovery(Action? configureAuto /// public void ConfigureResourceGraph(ICollection dbContextTypes, Action? configureResourceGraph) { - ArgumentGuard.NotNull(dbContextTypes); + ArgumentNullException.ThrowIfNull(dbContextTypes); _services.TryAddSingleton(serviceProvider => { var loggerFactory = serviceProvider.GetRequiredService(); + var events = serviceProvider.GetRequiredService(); + var resourceGraphBuilder = new ResourceGraphBuilder(_options, loggerFactory); var scanner = new ResourcesAssemblyScanner(_assemblyCache, resourceGraphBuilder); @@ -93,8 +94,7 @@ public void ConfigureResourceGraph(ICollection dbContextTypes, Action public void ConfigureServiceContainer(ICollection dbContextTypes) { - ArgumentGuard.NotNull(dbContextTypes); + ArgumentNullException.ThrowIfNull(dbContextTypes); - if (dbContextTypes.Any()) + if (dbContextTypes.Count > 0) { _services.TryAddScoped(typeof(DbContextResolver<>)); @@ -169,6 +169,7 @@ public void ConfigureServiceContainer(ICollection dbContextTypes) _services.TryAddScoped(); _services.TryAddScoped(); _services.TryAddSingleton(); + _services.TryAddSingleton(); } private void AddMiddlewareLayer() @@ -183,7 +184,9 @@ private void AddMiddlewareLayer() _services.TryAddSingleton(); _services.TryAddSingleton(); _services.TryAddSingleton(provider => provider.GetRequiredService()); + _services.TryAddSingleton(); _services.TryAddSingleton(); + _services.TryAddSingleton(); _services.TryAddScoped(); _services.TryAddScoped(); _services.TryAddScoped(); diff --git a/src/JsonApiDotNetCore/Configuration/JsonApiModelMetadataProvider.cs b/src/JsonApiDotNetCore/Configuration/JsonApiModelMetadataProvider.cs index 0f9cbf1fd2..5e1941a165 100644 --- a/src/JsonApiDotNetCore/Configuration/JsonApiModelMetadataProvider.cs +++ b/src/JsonApiDotNetCore/Configuration/JsonApiModelMetadataProvider.cs @@ -31,6 +31,8 @@ public JsonApiModelMetadataProvider(ICompositeMetadataDetailsProvider detailsPro /// protected override ModelMetadata CreateModelMetadata(DefaultMetadataDetails entry) { + ArgumentNullException.ThrowIfNull(entry); + var metadata = (DefaultModelMetadata)base.CreateModelMetadata(entry); metadata.ValidationMetadata.PropertyValidationFilter = _jsonApiValidationFilter; diff --git a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs index fb0b310118..182c51431b 100644 --- a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs +++ b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs @@ -2,6 +2,7 @@ using System.Text.Encodings.Web; using System.Text.Json; using JetBrains.Annotations; +using JsonApiDotNetCore.Middleware; using JsonApiDotNetCore.Resources.Annotations; using JsonApiDotNetCore.Serialization.JsonConverters; @@ -11,6 +12,7 @@ namespace JsonApiDotNetCore.Configuration; [PublicAPI] public sealed class JsonApiOptions : IJsonApiOptions { + private static readonly IReadOnlySet EmptyExtensionSet = new HashSet().AsReadOnly(); private readonly Lazy _lazySerializerWriteOptions; private readonly Lazy _lazySerializerReadOptions; @@ -97,6 +99,9 @@ public bool AllowClientGeneratedIds /// public IsolationLevel? TransactionIsolationLevel { get; set; } + /// + public IReadOnlySet Extensions { get; set; } = EmptyExtensionSet; + /// public JsonSerializerOptions SerializerOptions { get; } = new() { @@ -130,4 +135,27 @@ public JsonApiOptions() } }, LazyThreadSafetyMode.ExecutionAndPublication); } + + /// + /// Adds the specified JSON:API extensions to the existing set. + /// + /// + /// The JSON:API extensions to add. + /// + public void IncludeExtensions(params JsonApiMediaTypeExtension[] extensionsToAdd) + { + ArgumentNullException.ThrowIfNull(extensionsToAdd); + + if (!Extensions.IsSupersetOf(extensionsToAdd)) + { + var extensions = new HashSet(Extensions); + + foreach (JsonApiMediaTypeExtension extension in extensionsToAdd) + { + extensions.Add(extension); + } + + Extensions = extensions.AsReadOnly(); + } + } } diff --git a/src/JsonApiDotNetCore/Configuration/JsonApiValidationFilter.cs b/src/JsonApiDotNetCore/Configuration/JsonApiValidationFilter.cs index 3fd29a9c65..30b850e8b8 100644 --- a/src/JsonApiDotNetCore/Configuration/JsonApiValidationFilter.cs +++ b/src/JsonApiDotNetCore/Configuration/JsonApiValidationFilter.cs @@ -16,7 +16,7 @@ internal sealed class JsonApiValidationFilter : IPropertyValidationFilter public JsonApiValidationFilter(IHttpContextAccessor httpContextAccessor) { - ArgumentGuard.NotNull(httpContextAccessor); + ArgumentNullException.ThrowIfNull(httpContextAccessor); _httpContextAccessor = httpContextAccessor; } diff --git a/src/JsonApiDotNetCore/Configuration/PageNumber.cs b/src/JsonApiDotNetCore/Configuration/PageNumber.cs index a2d4c0cba0..f4af725a3d 100644 --- a/src/JsonApiDotNetCore/Configuration/PageNumber.cs +++ b/src/JsonApiDotNetCore/Configuration/PageNumber.cs @@ -11,17 +11,14 @@ public sealed class PageNumber : IEquatable public PageNumber(int oneBasedValue) { - if (oneBasedValue < 1) - { - throw new ArgumentOutOfRangeException(nameof(oneBasedValue)); - } + ArgumentOutOfRangeException.ThrowIfLessThan(oneBasedValue, 1); OneBasedValue = oneBasedValue; } public bool Equals(PageNumber? other) { - if (ReferenceEquals(null, other)) + if (other is null) { return false; } diff --git a/src/JsonApiDotNetCore/Configuration/PageSize.cs b/src/JsonApiDotNetCore/Configuration/PageSize.cs index 7f926f519e..4581992597 100644 --- a/src/JsonApiDotNetCore/Configuration/PageSize.cs +++ b/src/JsonApiDotNetCore/Configuration/PageSize.cs @@ -9,17 +9,14 @@ public sealed class PageSize : IEquatable public PageSize(int value) { - if (value < 1) - { - throw new ArgumentOutOfRangeException(nameof(value)); - } + ArgumentOutOfRangeException.ThrowIfLessThan(value, 1); Value = value; } public bool Equals(PageSize? other) { - if (ReferenceEquals(null, other)) + if (other is null) { return false; } diff --git a/src/JsonApiDotNetCore/Configuration/ResourceDescriptor.cs b/src/JsonApiDotNetCore/Configuration/ResourceDescriptor.cs index 885f67567c..9c0ce2cf30 100644 --- a/src/JsonApiDotNetCore/Configuration/ResourceDescriptor.cs +++ b/src/JsonApiDotNetCore/Configuration/ResourceDescriptor.cs @@ -7,8 +7,8 @@ internal sealed class ResourceDescriptor public ResourceDescriptor(Type resourceClrType, Type idClrType) { - ArgumentGuard.NotNull(resourceClrType); - ArgumentGuard.NotNull(idClrType); + ArgumentNullException.ThrowIfNull(resourceClrType); + ArgumentNullException.ThrowIfNull(idClrType); ResourceClrType = resourceClrType; IdClrType = idClrType; diff --git a/src/JsonApiDotNetCore/Configuration/ResourceDescriptorAssemblyCache.cs b/src/JsonApiDotNetCore/Configuration/ResourceDescriptorAssemblyCache.cs index a220d96e01..78d83425ce 100644 --- a/src/JsonApiDotNetCore/Configuration/ResourceDescriptorAssemblyCache.cs +++ b/src/JsonApiDotNetCore/Configuration/ResourceDescriptorAssemblyCache.cs @@ -8,7 +8,7 @@ namespace JsonApiDotNetCore.Configuration; internal sealed class ResourceDescriptorAssemblyCache { private readonly TypeLocator _typeLocator = new(); - private readonly Dictionary?> _resourceDescriptorsPerAssembly = []; + private readonly Dictionary _resourceDescriptorsPerAssembly = []; public void RegisterAssembly(Assembly assembly) { @@ -19,7 +19,7 @@ public IReadOnlyCollection GetResourceDescriptors() { EnsureAssembliesScanned(); - return _resourceDescriptorsPerAssembly.SelectMany(pair => pair.Value!).ToArray(); + return _resourceDescriptorsPerAssembly.SelectMany(pair => pair.Value!).ToArray().AsReadOnly(); } public IReadOnlyCollection GetAssemblies() diff --git a/src/JsonApiDotNetCore/Configuration/ResourceGraph.cs b/src/JsonApiDotNetCore/Configuration/ResourceGraph.cs index e763ec2ae0..a4ffd082d3 100644 --- a/src/JsonApiDotNetCore/Configuration/ResourceGraph.cs +++ b/src/JsonApiDotNetCore/Configuration/ResourceGraph.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using System.Linq.Expressions; using System.Reflection; using JetBrains.Annotations; @@ -18,7 +19,7 @@ public sealed class ResourceGraph : IResourceGraph public ResourceGraph(IReadOnlySet resourceTypeSet) { - ArgumentGuard.NotNull(resourceTypeSet); + ArgumentNullException.ThrowIfNull(resourceTypeSet); _resourceTypeSet = resourceTypeSet; @@ -51,7 +52,7 @@ public ResourceType GetResourceType(string publicName) /// public ResourceType? FindResourceType(string publicName) { - ArgumentGuard.NotNull(publicName); + ArgumentNullException.ThrowIfNull(publicName); return _resourceTypesByPublicName.GetValueOrDefault(publicName); } @@ -72,7 +73,7 @@ public ResourceType GetResourceType(Type resourceClrType) /// public ResourceType? FindResourceType(Type resourceClrType) { - ArgumentGuard.NotNull(resourceClrType); + ArgumentNullException.ThrowIfNull(resourceClrType); Type typeToFind = IsLazyLoadingProxyForResourceType(resourceClrType) ? resourceClrType.BaseType! : resourceClrType; return _resourceTypesByClrType.GetValueOrDefault(typeToFind); @@ -94,7 +95,7 @@ public ResourceType GetResourceType() public IReadOnlyCollection GetFields(Expression> selector) where TResource : class, IIdentifiable { - ArgumentGuard.NotNull(selector); + ArgumentNullException.ThrowIfNull(selector); return FilterFields(selector); } @@ -103,7 +104,7 @@ public IReadOnlyCollection GetFields(Expressi public IReadOnlyCollection GetAttributes(Expression> selector) where TResource : class, IIdentifiable { - ArgumentGuard.NotNull(selector); + ArgumentNullException.ThrowIfNull(selector); return FilterFields(selector); } @@ -112,17 +113,17 @@ public IReadOnlyCollection GetAttributes(Expression GetRelationships(Expression> selector) where TResource : class, IIdentifiable { - ArgumentGuard.NotNull(selector); + ArgumentNullException.ThrowIfNull(selector); return FilterFields(selector); } - private IReadOnlyCollection FilterFields(Expression> selector) + private ReadOnlyCollection FilterFields(Expression> selector) where TResource : class, IIdentifiable where TField : ResourceFieldAttribute { IReadOnlyCollection source = GetFieldsOfType(); - var matches = new List(); + List matches = []; foreach (string memberName in ToMemberNames(selector)) { @@ -136,7 +137,7 @@ private IReadOnlyCollection FilterFields(Expression GetFieldsOfType() diff --git a/src/JsonApiDotNetCore/Configuration/ResourceGraphBuilder.cs b/src/JsonApiDotNetCore/Configuration/ResourceGraphBuilder.cs index b0ebd8bb60..7cdf04404b 100644 --- a/src/JsonApiDotNetCore/Configuration/ResourceGraphBuilder.cs +++ b/src/JsonApiDotNetCore/Configuration/ResourceGraphBuilder.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using System.Reflection; using JetBrains.Annotations; using JsonApiDotNetCore.Errors; @@ -13,7 +14,7 @@ namespace JsonApiDotNetCore.Configuration; /// Builds and configures the . /// [PublicAPI] -public class ResourceGraphBuilder +public partial class ResourceGraphBuilder { private readonly IJsonApiOptions _options; private readonly ILogger _logger; @@ -22,8 +23,8 @@ public class ResourceGraphBuilder public ResourceGraphBuilder(IJsonApiOptions options, ILoggerFactory loggerFactory) { - ArgumentGuard.NotNull(options); - ArgumentGuard.NotNull(loggerFactory); + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(loggerFactory); _options = options; _logger = loggerFactory.CreateLogger(); @@ -34,11 +35,11 @@ public ResourceGraphBuilder(IJsonApiOptions options, ILoggerFactory loggerFactor /// public IResourceGraph Build() { - HashSet resourceTypes = [.. _resourceTypesByClrType.Values]; + IReadOnlySet resourceTypes = _resourceTypesByClrType.Values.ToHashSet().AsReadOnly(); - if (!resourceTypes.Any()) + if (resourceTypes.Count == 0) { - _logger.LogWarning("The resource graph is empty."); + LogResourceGraphIsEmpty(); } var resourceGraph = new ResourceGraph(resourceTypes); @@ -71,8 +72,8 @@ private static void SetRelationshipTypes(ResourceGraph resourceGraph) if (rightType == null) { - throw new InvalidConfigurationException($"Resource type '{relationship.LeftType.ClrType}' depends on " + - $"'{rightClrType}', which was not added to the resource graph."); + throw new InvalidConfigurationException( + $"Resource type '{relationship.LeftType.ClrType}' depends on '{rightClrType}', which was not added to the resource graph."); } relationship.RightType = rightType; @@ -91,18 +92,22 @@ private static void SetDirectlyDerivedTypes(ResourceGraph resourceGraph) { resourceType.BaseType = baseType; - if (!directlyDerivedTypesPerBaseType.ContainsKey(baseType)) + if (!directlyDerivedTypesPerBaseType.TryGetValue(baseType, out HashSet? directlyDerivedTypes)) { - directlyDerivedTypesPerBaseType[baseType] = []; + directlyDerivedTypes = []; + directlyDerivedTypesPerBaseType[baseType] = directlyDerivedTypes; } - directlyDerivedTypesPerBaseType[baseType].Add(resourceType); + directlyDerivedTypes.Add(resourceType); } } foreach ((ResourceType baseType, HashSet directlyDerivedTypes) in directlyDerivedTypesPerBaseType) { - baseType.DirectlyDerivedTypes = directlyDerivedTypes; + if (directlyDerivedTypes.Count > 0) + { + baseType.DirectlyDerivedTypes = directlyDerivedTypes.AsReadOnly(); + } } } @@ -124,8 +129,8 @@ private static void ValidateAttributesInDerivedType(ResourceType resourceType) { if (resourceType.FindAttributeByPublicName(attribute.PublicName) == null) { - throw new InvalidConfigurationException($"Attribute '{attribute.PublicName}' from base type " + - $"'{resourceType.BaseType.ClrType}' does not exist in derived type '{resourceType.ClrType}'."); + throw new InvalidConfigurationException( + $"Attribute '{attribute.PublicName}' from base type '{resourceType.BaseType.ClrType}' does not exist in derived type '{resourceType.ClrType}'."); } } } @@ -136,15 +141,15 @@ private static void ValidateRelationshipsInDerivedType(ResourceType resourceType { if (resourceType.FindRelationshipByPublicName(relationship.PublicName) == null) { - throw new InvalidConfigurationException($"Relationship '{relationship.PublicName}' from base type " + - $"'{resourceType.BaseType.ClrType}' does not exist in derived type '{resourceType.ClrType}'."); + throw new InvalidConfigurationException( + $"Relationship '{relationship.PublicName}' from base type '{resourceType.BaseType.ClrType}' does not exist in derived type '{resourceType.ClrType}'."); } } } public ResourceGraphBuilder Add(DbContext dbContext) { - ArgumentGuard.NotNull(dbContext); + ArgumentNullException.ThrowIfNull(dbContext); foreach (IEntityType entityType in dbContext.Model.GetEntityTypes()) { @@ -200,7 +205,7 @@ public ResourceGraphBuilder Add(string? publicName = null) public ResourceGraphBuilder Add(Type resourceClrType, Type? idClrType = null, string? publicName = null) #pragma warning restore AV1553 // Do not use optional parameters with default value null for strings, collections or tasks { - ArgumentGuard.NotNull(resourceClrType); + ArgumentNullException.ThrowIfNull(resourceClrType); if (_resourceTypesByClrType.ContainsKey(resourceClrType)) { @@ -227,8 +232,7 @@ public ResourceGraphBuilder Add(Type resourceClrType, Type? idClrType = null, st { if (resourceClrType.GetCustomAttribute() == null) { - _logger.LogWarning( - $"Skipping: Type '{resourceClrType}' does not implement '{nameof(IIdentifiable)}'. Add [NoResource] to suppress this warning."); + LogResourceTypeDoesNotImplementInterface(resourceClrType, nameof(IIdentifiable)); } } @@ -239,9 +243,9 @@ private ResourceType CreateResourceType(string publicName, Type resourceClrType, { ClientIdGenerationMode? clientIdGeneration = GetClientIdGeneration(resourceClrType); - IReadOnlyCollection attributes = GetAttributes(resourceClrType); - IReadOnlyCollection relationships = GetRelationships(resourceClrType); - IReadOnlyCollection eagerLoads = GetEagerLoads(resourceClrType); + Dictionary.ValueCollection attributes = GetAttributes(resourceClrType); + Dictionary.ValueCollection relationships = GetRelationships(resourceClrType); + ReadOnlyCollection eagerLoads = GetEagerLoads(resourceClrType); AssertNoDuplicatePublicName(attributes, relationships); @@ -259,7 +263,7 @@ private ResourceType CreateResourceType(string publicName, Type resourceClrType, return resourceAttribute?.NullableClientIdGeneration; } - private IReadOnlyCollection GetAttributes(Type resourceClrType) + private Dictionary.ValueCollection GetAttributes(Type resourceClrType) { var attributesByName = new Dictionary(); @@ -296,13 +300,13 @@ private IReadOnlyCollection GetAttributes(Type resourceClrType) if (attributesByName.Count < 2) { - _logger.LogWarning($"Type '{resourceClrType}' does not contain any attributes."); + LogResourceTypeHasNoAttributes(resourceClrType); } return attributesByName.Values; } - private IReadOnlyCollection GetRelationships(Type resourceClrType) + private Dictionary.ValueCollection GetRelationships(Type resourceClrType) { var relationshipsByName = new Dictionary(); PropertyInfo[] properties = resourceClrType.GetProperties(); @@ -376,11 +380,11 @@ private void SetHasManyRelationshipCapabilities(HasManyAttribute hasManyRelation } } - private IReadOnlyCollection GetEagerLoads(Type resourceClrType, int recursionDepth = 0) + private ReadOnlyCollection GetEagerLoads(Type resourceClrType, int recursionDepth = 0) { AssertNoInfiniteRecursion(recursionDepth); - var attributes = new List(); + List eagerLoads = []; PropertyInfo[] properties = resourceClrType.GetProperties(); foreach (PropertyInfo property in properties) @@ -396,10 +400,10 @@ private IReadOnlyCollection GetEagerLoads(Type resourceClrTy eagerLoad.Children = GetEagerLoads(innerType, recursionDepth + 1); eagerLoad.Property = property; - attributes.Add(eagerLoad); + eagerLoads.Add(eagerLoad); } - return attributes; + return eagerLoads.AsReadOnly(); } private static void IncludeField(Dictionary fieldsByName, TField field) @@ -475,4 +479,14 @@ private string FormatPropertyName(PropertyInfo resourceProperty) ? resourceProperty.Name : _options.SerializerOptions.PropertyNamingPolicy.ConvertName(resourceProperty.Name); } + + [LoggerMessage(Level = LogLevel.Warning, Message = "The resource graph is empty.")] + private partial void LogResourceGraphIsEmpty(); + + [LoggerMessage(Level = LogLevel.Warning, + Message = "Skipping: Type '{ResourceType}' does not implement '{InterfaceType}'. Add [NoResource] to suppress this warning.")] + private partial void LogResourceTypeDoesNotImplementInterface(Type resourceType, string interfaceType); + + [LoggerMessage(Level = LogLevel.Warning, Message = "Type '{ResourceType}' does not contain any attributes.")] + private partial void LogResourceTypeHasNoAttributes(Type resourceType); } diff --git a/src/JsonApiDotNetCore/Configuration/ResourceNameFormatter.cs b/src/JsonApiDotNetCore/Configuration/ResourceNameFormatter.cs index 6a5a09dcaf..0531c25ca9 100644 --- a/src/JsonApiDotNetCore/Configuration/ResourceNameFormatter.cs +++ b/src/JsonApiDotNetCore/Configuration/ResourceNameFormatter.cs @@ -14,7 +14,7 @@ internal sealed class ResourceNameFormatter(JsonNamingPolicy? namingPolicy) /// public string FormatResourceName(Type resourceClrType) { - ArgumentGuard.NotNull(resourceClrType); + ArgumentNullException.ThrowIfNull(resourceClrType); var resourceAttribute = resourceClrType.GetCustomAttribute(true); diff --git a/src/JsonApiDotNetCore/Configuration/ResourcesAssemblyScanner.cs b/src/JsonApiDotNetCore/Configuration/ResourcesAssemblyScanner.cs index cdfdc4446c..f2dcf827d3 100644 --- a/src/JsonApiDotNetCore/Configuration/ResourcesAssemblyScanner.cs +++ b/src/JsonApiDotNetCore/Configuration/ResourcesAssemblyScanner.cs @@ -12,8 +12,8 @@ internal sealed class ResourcesAssemblyScanner public ResourcesAssemblyScanner(ResourceDescriptorAssemblyCache assemblyCache, ResourceGraphBuilder resourceGraphBuilder) { - ArgumentGuard.NotNull(assemblyCache); - ArgumentGuard.NotNull(resourceGraphBuilder); + ArgumentNullException.ThrowIfNull(assemblyCache); + ArgumentNullException.ThrowIfNull(resourceGraphBuilder); _assemblyCache = assemblyCache; _resourceGraphBuilder = resourceGraphBuilder; diff --git a/src/JsonApiDotNetCore/Configuration/ServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Configuration/ServiceCollectionExtensions.cs index 5ad4474d95..65bf465ce3 100644 --- a/src/JsonApiDotNetCore/Configuration/ServiceCollectionExtensions.cs +++ b/src/JsonApiDotNetCore/Configuration/ServiceCollectionExtensions.cs @@ -22,7 +22,7 @@ public static IServiceCollection AddJsonApi(this IServiceCollection services, Ac ICollection? dbContextTypes = null) #pragma warning restore AV1553 // Do not use optional parameters with default value null for strings, collections or tasks { - ArgumentGuard.NotNull(services); + ArgumentNullException.ThrowIfNull(services); SetupApplicationBuilder(services, options, discovery, resources, mvcBuilder, dbContextTypes ?? Array.Empty()); @@ -59,7 +59,7 @@ private static void SetupApplicationBuilder(IServiceCollection services, Action< /// public static IServiceCollection AddResourceService(this IServiceCollection services) { - ArgumentGuard.NotNull(services); + ArgumentNullException.ThrowIfNull(services); RegisterTypeForUnboundInterfaces(services, typeof(TService), InjectablesAssemblyScanner.ServiceUnboundInterfaces); @@ -72,7 +72,7 @@ public static IServiceCollection AddResourceService(this IServiceColle /// public static IServiceCollection AddResourceRepository(this IServiceCollection services) { - ArgumentGuard.NotNull(services); + ArgumentNullException.ThrowIfNull(services); RegisterTypeForUnboundInterfaces(services, typeof(TRepository), InjectablesAssemblyScanner.RepositoryUnboundInterfaces); @@ -85,7 +85,7 @@ public static IServiceCollection AddResourceRepository(this IServic /// public static IServiceCollection AddResourceDefinition(this IServiceCollection services) { - ArgumentGuard.NotNull(services); + ArgumentNullException.ThrowIfNull(services); RegisterTypeForUnboundInterfaces(services, typeof(TResourceDefinition), InjectablesAssemblyScanner.ResourceDefinitionUnboundInterfaces); diff --git a/src/JsonApiDotNetCore/Configuration/ServiceDiscoveryFacade.cs b/src/JsonApiDotNetCore/Configuration/ServiceDiscoveryFacade.cs index 615ef244fc..d28b8381c6 100644 --- a/src/JsonApiDotNetCore/Configuration/ServiceDiscoveryFacade.cs +++ b/src/JsonApiDotNetCore/Configuration/ServiceDiscoveryFacade.cs @@ -13,7 +13,7 @@ public sealed class ServiceDiscoveryFacade internal ServiceDiscoveryFacade(ResourceDescriptorAssemblyCache assemblyCache) { - ArgumentGuard.NotNull(assemblyCache); + ArgumentNullException.ThrowIfNull(assemblyCache); _assemblyCache = assemblyCache; } @@ -31,7 +31,7 @@ public ServiceDiscoveryFacade AddCurrentAssembly() /// public ServiceDiscoveryFacade AddAssembly(Assembly assembly) { - ArgumentGuard.NotNull(assembly); + ArgumentNullException.ThrowIfNull(assembly); _assemblyCache.RegisterAssembly(assembly); return this; diff --git a/src/JsonApiDotNetCore/Configuration/TypeLocator.cs b/src/JsonApiDotNetCore/Configuration/TypeLocator.cs index 9f65b46b97..6b8c545744 100644 --- a/src/JsonApiDotNetCore/Configuration/TypeLocator.cs +++ b/src/JsonApiDotNetCore/Configuration/TypeLocator.cs @@ -66,9 +66,9 @@ internal sealed class TypeLocator public (Type implementationType, Type serviceInterface)? GetContainerRegistrationFromAssembly(Assembly assembly, Type unboundInterface, params Type[] interfaceTypeArguments) { - ArgumentGuard.NotNull(assembly); - ArgumentGuard.NotNull(unboundInterface); - ArgumentGuard.NotNull(interfaceTypeArguments); + ArgumentNullException.ThrowIfNull(assembly); + ArgumentNullException.ThrowIfNull(unboundInterface); + ArgumentNullException.ThrowIfNull(interfaceTypeArguments); if (!unboundInterface.IsInterface || !unboundInterface.IsGenericType || unboundInterface != unboundInterface.GetGenericTypeDefinition()) { @@ -110,33 +110,6 @@ private static (Type implementationType, Type serviceInterface)? GetContainerReg return null; } - /// - /// Scans for types in the specified assembly that derive from the specified unbound generic type. - /// - /// - /// The assembly to search for derived types. - /// - /// - /// The unbound generic type to match against. - /// - /// - /// Generic type arguments to construct . - /// - /// - /// ), typeof(Article), typeof(int)) - /// ]]> - /// - public IReadOnlyCollection GetDerivedTypesForUnboundType(Assembly assembly, Type unboundType, params Type[] typeArguments) - { - ArgumentGuard.NotNull(assembly); - ArgumentGuard.NotNull(unboundType); - ArgumentGuard.NotNull(typeArguments); - - Type closedType = unboundType.MakeGenericType(typeArguments); - return GetDerivedTypes(assembly, closedType).ToArray(); - } - /// /// Gets all derivatives of the specified type. /// @@ -153,8 +126,8 @@ public IReadOnlyCollection GetDerivedTypesForUnboundType(Assembly assembly /// public IEnumerable GetDerivedTypes(Assembly assembly, Type baseType) { - ArgumentGuard.NotNull(assembly); - ArgumentGuard.NotNull(baseType); + ArgumentNullException.ThrowIfNull(assembly); + ArgumentNullException.ThrowIfNull(baseType); foreach (Type type in assembly.GetTypes()) { diff --git a/src/JsonApiDotNetCore/Controllers/Annotations/DisableQueryStringAttribute.cs b/src/JsonApiDotNetCore/Controllers/Annotations/DisableQueryStringAttribute.cs index eba4b8340c..d90d67118e 100644 --- a/src/JsonApiDotNetCore/Controllers/Annotations/DisableQueryStringAttribute.cs +++ b/src/JsonApiDotNetCore/Controllers/Annotations/DisableQueryStringAttribute.cs @@ -27,7 +27,7 @@ public sealed class DisableQueryStringAttribute : Attribute /// public DisableQueryStringAttribute(JsonApiQueryStringParameters parameters) { - var parameterNames = new HashSet(); + HashSet parameterNames = []; foreach (JsonApiQueryStringParameters value in Enum.GetValues()) { @@ -37,7 +37,7 @@ public DisableQueryStringAttribute(JsonApiQueryStringParameters parameters) } } - ParameterNames = parameterNames; + ParameterNames = parameterNames.AsReadOnly(); } /// @@ -46,9 +46,9 @@ public DisableQueryStringAttribute(JsonApiQueryStringParameters parameters) /// public DisableQueryStringAttribute(string parameterNames) { - ArgumentGuard.NotNullNorEmpty(parameterNames); + ArgumentException.ThrowIfNullOrEmpty(parameterNames); - ParameterNames = parameterNames.Split(",").ToHashSet(); + ParameterNames = parameterNames.Split(",").ToHashSet().AsReadOnly(); } public bool ContainsParameter(JsonApiQueryStringParameters parameter) diff --git a/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs b/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs index bef962a971..acd6528500 100644 --- a/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs +++ b/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs @@ -66,9 +66,9 @@ protected BaseJsonApiController(IJsonApiOptions options, IResourceGraph resource IUpdateService? update = null, ISetRelationshipService? setRelationship = null, IDeleteService? delete = null, IRemoveFromRelationshipService? removeFromRelationship = null) { - ArgumentGuard.NotNull(options); - ArgumentGuard.NotNull(resourceGraph); - ArgumentGuard.NotNull(loggerFactory); + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(resourceGraph); + ArgumentNullException.ThrowIfNull(loggerFactory); _options = options; _resourceGraph = resourceGraph; @@ -134,7 +134,8 @@ public virtual async Task GetAsync([DisallowNull] TId id, Cancell /// GET /articles/1/revisions HTTP/1.1 /// ]]> /// - public virtual async Task GetSecondaryAsync([DisallowNull] TId id, string relationshipName, CancellationToken cancellationToken) + public virtual async Task GetSecondaryAsync([DisallowNull] TId id, [PreserveEmptyString] string relationshipName, + CancellationToken cancellationToken) { _traceWriter.LogMethodStart(new { @@ -142,7 +143,7 @@ public virtual async Task GetSecondaryAsync([DisallowNull] TId id relationshipName }); - ArgumentGuard.NotNullNorEmpty(relationshipName); + ArgumentNullException.ThrowIfNull(relationshipName); if (_getSecondary == null) { @@ -163,7 +164,8 @@ public virtual async Task GetSecondaryAsync([DisallowNull] TId id /// GET /articles/1/relationships/revisions HTTP/1.1 /// ]]> /// - public virtual async Task GetRelationshipAsync([DisallowNull] TId id, string relationshipName, CancellationToken cancellationToken) + public virtual async Task GetRelationshipAsync([DisallowNull] TId id, [PreserveEmptyString] string relationshipName, + CancellationToken cancellationToken) { _traceWriter.LogMethodStart(new { @@ -171,7 +173,7 @@ public virtual async Task GetRelationshipAsync([DisallowNull] TId relationshipName }); - ArgumentGuard.NotNullNorEmpty(relationshipName); + ArgumentNullException.ThrowIfNull(relationshipName); if (_getRelationship == null) { @@ -195,7 +197,7 @@ public virtual async Task PostAsync([FromBody] TResource resource resource }); - ArgumentGuard.NotNull(resource); + ArgumentNullException.ThrowIfNull(resource); if (_create == null) { @@ -214,7 +216,7 @@ public virtual async Task PostAsync([FromBody] TResource resource if (newResource == null) { - HttpContext.Response.Headers["Location"] = locationUrl; + HttpContext.Response.Headers.Location = locationUrl; return NoContent(); } @@ -247,7 +249,7 @@ private string GetLocationUrl(string resourceId) /// /// Propagates notification that request handling should be canceled. /// - public virtual async Task PostRelationshipAsync([DisallowNull] TId id, string relationshipName, + public virtual async Task PostRelationshipAsync([DisallowNull] TId id, [PreserveEmptyString] string relationshipName, [FromBody] ISet rightResourceIds, CancellationToken cancellationToken) { _traceWriter.LogMethodStart(new @@ -257,8 +259,8 @@ public virtual async Task PostRelationshipAsync([DisallowNull] TI rightResourceIds }); - ArgumentGuard.NotNullNorEmpty(relationshipName); - ArgumentGuard.NotNull(rightResourceIds); + ArgumentNullException.ThrowIfNull(relationshipName); + ArgumentNullException.ThrowIfNull(rightResourceIds); if (_addToRelationship == null) { @@ -284,7 +286,7 @@ public virtual async Task PatchAsync([DisallowNull] TId id, [From resource }); - ArgumentGuard.NotNull(resource); + ArgumentNullException.ThrowIfNull(resource); if (_update == null) { @@ -322,8 +324,8 @@ public virtual async Task PatchAsync([DisallowNull] TId id, [From /// /// Propagates notification that request handling should be canceled. /// - public virtual async Task PatchRelationshipAsync([DisallowNull] TId id, string relationshipName, [FromBody] object? rightValue, - CancellationToken cancellationToken) + public virtual async Task PatchRelationshipAsync([DisallowNull] TId id, [PreserveEmptyString] string relationshipName, + [FromBody] object? rightValue, CancellationToken cancellationToken) { _traceWriter.LogMethodStart(new { @@ -332,7 +334,7 @@ public virtual async Task PatchRelationshipAsync([DisallowNull] T rightValue }); - ArgumentGuard.NotNullNorEmpty(relationshipName); + ArgumentNullException.ThrowIfNull(relationshipName); if (_setRelationship == null) { @@ -383,7 +385,7 @@ public virtual async Task DeleteAsync([DisallowNull] TId id, Canc /// /// Propagates notification that request handling should be canceled. /// - public virtual async Task DeleteRelationshipAsync([DisallowNull] TId id, string relationshipName, + public virtual async Task DeleteRelationshipAsync([DisallowNull] TId id, [PreserveEmptyString] string relationshipName, [FromBody] ISet rightResourceIds, CancellationToken cancellationToken) { _traceWriter.LogMethodStart(new @@ -393,8 +395,8 @@ public virtual async Task DeleteRelationshipAsync([DisallowNull] rightResourceIds }); - ArgumentGuard.NotNullNorEmpty(relationshipName); - ArgumentGuard.NotNull(rightResourceIds); + ArgumentNullException.ThrowIfNull(relationshipName); + ArgumentNullException.ThrowIfNull(rightResourceIds); if (_removeFromRelationship == null) { diff --git a/src/JsonApiDotNetCore/Controllers/BaseJsonApiOperationsController.cs b/src/JsonApiDotNetCore/Controllers/BaseJsonApiOperationsController.cs index b169bdd005..6c6703c132 100644 --- a/src/JsonApiDotNetCore/Controllers/BaseJsonApiOperationsController.cs +++ b/src/JsonApiDotNetCore/Controllers/BaseJsonApiOperationsController.cs @@ -30,13 +30,13 @@ public abstract class BaseJsonApiOperationsController : CoreJsonApiController protected BaseJsonApiOperationsController(IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, IOperationsProcessor processor, IJsonApiRequest request, ITargetedFields targetedFields, IAtomicOperationFilter operationFilter) { - ArgumentGuard.NotNull(options); - ArgumentGuard.NotNull(resourceGraph); - ArgumentGuard.NotNull(loggerFactory); - ArgumentGuard.NotNull(processor); - ArgumentGuard.NotNull(request); - ArgumentGuard.NotNull(targetedFields); - ArgumentGuard.NotNull(operationFilter); + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(resourceGraph); + ArgumentNullException.ThrowIfNull(loggerFactory); + ArgumentNullException.ThrowIfNull(processor); + ArgumentNullException.ThrowIfNull(request); + ArgumentNullException.ThrowIfNull(targetedFields); + ArgumentNullException.ThrowIfNull(operationFilter); _options = options; _resourceGraph = resourceGraph; @@ -114,7 +114,7 @@ public virtual async Task PostOperationsAsync([FromBody] IList PostOperationsAsync([FromBody] IList operations) { + ArgumentNullException.ThrowIfNull(operations); + List errors = []; for (int operationIndex = 0; operationIndex < operations.Count; operationIndex++) { IJsonApiRequest operationRequest = operations[operationIndex].Request; - WriteOperationKind operationKind = operationRequest.WriteOperation!.Value; + WriteOperationKind writeOperation = operationRequest.WriteOperation!.Value; - if (operationRequest.Relationship != null && !_operationFilter.IsEnabled(operationRequest.Relationship.LeftType, operationKind)) + if (operationRequest.Relationship != null && !_operationFilter.IsEnabled(operationRequest.Relationship.LeftType, writeOperation)) { - string operationCode = GetOperationCodeText(operationKind); + string operationCode = GetOperationCodeText(writeOperation); errors.Add(new ErrorObject(HttpStatusCode.Forbidden) { @@ -151,9 +153,9 @@ protected virtual void ValidateEnabledOperations(IList opera } }); } - else if (operationRequest.PrimaryResourceType != null && !_operationFilter.IsEnabled(operationRequest.PrimaryResourceType, operationKind)) + else if (operationRequest.PrimaryResourceType != null && !_operationFilter.IsEnabled(operationRequest.PrimaryResourceType, writeOperation)) { - string operationCode = GetOperationCodeText(operationKind); + string operationCode = GetOperationCodeText(writeOperation); errors.Add(new ErrorObject(HttpStatusCode.Forbidden) { @@ -173,9 +175,9 @@ protected virtual void ValidateEnabledOperations(IList opera } } - private static string GetOperationCodeText(WriteOperationKind operationKind) + private static string GetOperationCodeText(WriteOperationKind writeOperation) { - AtomicOperationCode operationCode = operationKind switch + AtomicOperationCode operationCode = writeOperation switch { WriteOperationKind.CreateResource => AtomicOperationCode.Add, WriteOperationKind.UpdateResource => AtomicOperationCode.Update, @@ -183,7 +185,7 @@ private static string GetOperationCodeText(WriteOperationKind operationKind) WriteOperationKind.AddToRelationship => AtomicOperationCode.Add, WriteOperationKind.SetRelationship => AtomicOperationCode.Update, WriteOperationKind.RemoveFromRelationship => AtomicOperationCode.Remove, - _ => throw new NotSupportedException($"Unknown operation kind '{operationKind}'.") + _ => throw new NotSupportedException($"Unknown operation kind '{writeOperation}'.") }; return operationCode.ToString().ToLowerInvariant(); @@ -191,13 +193,15 @@ private static string GetOperationCodeText(WriteOperationKind operationKind) protected virtual void ValidateModelState(IList operations) { + ArgumentNullException.ThrowIfNull(operations); + // We must validate the resource inside each operation manually, because they are typed as IIdentifiable. // Instead of validating IIdentifiable we need to validate the resource runtime-type. using IDisposable _ = new RevertRequestStateOnDispose(_request, _targetedFields); int operationIndex = 0; - var requestModelState = new List<(string key, ModelStateEntry? entry)>(); + List<(string key, ModelStateEntry? entry)> requestModelState = []; int maxErrorsRemaining = ModelState.MaxAllowedErrors; foreach (OperationContainer operation in operations) @@ -212,7 +216,7 @@ protected virtual void ValidateModelState(IList operations) operationIndex++; } - if (requestModelState.Any()) + if (requestModelState.Count > 0) { Dictionary modelStateDictionary = requestModelState.ToDictionary(tuple => tuple.key, tuple => tuple.entry); diff --git a/src/JsonApiDotNetCore/Controllers/CoreJsonApiController.cs b/src/JsonApiDotNetCore/Controllers/CoreJsonApiController.cs index b4626ba031..f81ec9d071 100644 --- a/src/JsonApiDotNetCore/Controllers/CoreJsonApiController.cs +++ b/src/JsonApiDotNetCore/Controllers/CoreJsonApiController.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using JsonApiDotNetCore.Serialization.Objects; using Microsoft.AspNetCore.Mvc; @@ -10,7 +11,7 @@ public abstract class CoreJsonApiController : ControllerBase { protected IActionResult Error(ErrorObject error) { - ArgumentGuard.NotNull(error); + ArgumentNullException.ThrowIfNull(error); return new ObjectResult(error) { @@ -20,17 +21,17 @@ protected IActionResult Error(ErrorObject error) protected IActionResult Error(IEnumerable errors) { - IReadOnlyList? errorList = ToErrorList(errors); - ArgumentGuard.NotNullNorEmpty(errorList); + ReadOnlyCollection? errorCollection = ToCollection(errors); + ArgumentGuard.NotNullNorEmpty(errorCollection, nameof(errors)); - return new ObjectResult(errorList) + return new ObjectResult(errorCollection) { - StatusCode = (int)ErrorObject.GetResponseStatusCode(errorList) + StatusCode = (int)ErrorObject.GetResponseStatusCode(errorCollection) }; } - private static IReadOnlyList? ToErrorList(IEnumerable? errors) + private static ReadOnlyCollection? ToCollection(IEnumerable? errors) { - return errors?.ToArray(); + return errors?.ToArray().AsReadOnly(); } } diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiCommandController.cs b/src/JsonApiDotNetCore/Controllers/JsonApiCommandController.cs index 290487cb76..cd58e2d18d 100644 --- a/src/JsonApiDotNetCore/Controllers/JsonApiCommandController.cs +++ b/src/JsonApiDotNetCore/Controllers/JsonApiCommandController.cs @@ -15,16 +15,8 @@ namespace JsonApiDotNetCore.Controllers; /// /// The resource identifier type. /// -public abstract class JsonApiCommandController : JsonApiController - where TResource : class, IIdentifiable -{ - /// - /// Creates an instance from a write-only service. - /// - protected JsonApiCommandController(IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, - IResourceCommandService commandService) - : base(options, resourceGraph, loggerFactory, null, null, null, null, commandService, commandService, commandService, commandService, commandService, - commandService) - { - } -} +public abstract class JsonApiCommandController( + IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, IResourceCommandService commandService) + : JsonApiController(options, resourceGraph, loggerFactory, null, null, null, null, commandService, commandService, commandService, + commandService, commandService, commandService) + where TResource : class, IIdentifiable; diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiController.cs b/src/JsonApiDotNetCore/Controllers/JsonApiController.cs index e5be3cbc71..84e4dad3b5 100644 --- a/src/JsonApiDotNetCore/Controllers/JsonApiController.cs +++ b/src/JsonApiDotNetCore/Controllers/JsonApiController.cs @@ -6,6 +6,8 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; +#pragma warning disable format + namespace JsonApiDotNetCore.Controllers; /// @@ -51,7 +53,7 @@ public override async Task GetAsync(CancellationToken cancellatio /// [HttpGet("{id}")] [HttpHead("{id}")] - public override async Task GetAsync([Required] [DisallowNull] TId id, CancellationToken cancellationToken) + public override async Task GetAsync([Required(AllowEmptyStrings = true)] [DisallowNull] TId id, CancellationToken cancellationToken) { return await base.GetAsync(id, cancellationToken); } @@ -59,7 +61,7 @@ public override async Task GetAsync([Required] [DisallowNull] TId /// [HttpGet("{id}/{relationshipName}")] [HttpHead("{id}/{relationshipName}")] - public override async Task GetSecondaryAsync([Required] [DisallowNull] TId id, [Required] string relationshipName, + public override async Task GetSecondaryAsync([Required(AllowEmptyStrings = true)] [DisallowNull] TId id, [Required] string relationshipName, CancellationToken cancellationToken) { return await base.GetSecondaryAsync(id, relationshipName, cancellationToken); @@ -68,8 +70,8 @@ public override async Task GetSecondaryAsync([Required] [Disallow /// [HttpGet("{id}/relationships/{relationshipName}")] [HttpHead("{id}/relationships/{relationshipName}")] - public override async Task GetRelationshipAsync([Required] [DisallowNull] TId id, [Required] string relationshipName, - CancellationToken cancellationToken) + public override async Task GetRelationshipAsync([Required(AllowEmptyStrings = true)] [DisallowNull] TId id, + [Required] string relationshipName, CancellationToken cancellationToken) { return await base.GetRelationshipAsync(id, relationshipName, cancellationToken); } @@ -83,39 +85,41 @@ public override async Task PostAsync([Required] TResource resourc /// [HttpPost("{id}/relationships/{relationshipName}")] - public override async Task PostRelationshipAsync([Required] [DisallowNull] TId id, [Required] string relationshipName, - [Required] ISet rightResourceIds, CancellationToken cancellationToken) + public override async Task PostRelationshipAsync([Required(AllowEmptyStrings = true)] [DisallowNull] TId id, + [Required] string relationshipName, [Required] ISet rightResourceIds, CancellationToken cancellationToken) { return await base.PostRelationshipAsync(id, relationshipName, rightResourceIds, cancellationToken); } /// [HttpPatch("{id}")] - public override async Task PatchAsync([Required] [DisallowNull] TId id, [Required] TResource resource, CancellationToken cancellationToken) + public override async Task PatchAsync([Required(AllowEmptyStrings = true)] [DisallowNull] TId id, [Required] TResource resource, + CancellationToken cancellationToken) { return await base.PatchAsync(id, resource, cancellationToken); } /// [HttpPatch("{id}/relationships/{relationshipName}")] + // `AllowEmptyStrings = true` in `[Required]` prevents the model binder from producing a validation error on whitespace when TId is string. // Parameter `[Required] object? rightValue` makes Swashbuckle generate the OpenAPI request body as required. We don't actually validate ModelState, so it doesn't hurt. - public override async Task PatchRelationshipAsync([Required] [DisallowNull] TId id, [Required] string relationshipName, - [Required] object? rightValue, CancellationToken cancellationToken) + public override async Task PatchRelationshipAsync([Required(AllowEmptyStrings = true)] [DisallowNull] TId id, + [Required] string relationshipName, [Required] object? rightValue, CancellationToken cancellationToken) { return await base.PatchRelationshipAsync(id, relationshipName, rightValue, cancellationToken); } /// [HttpDelete("{id}")] - public override async Task DeleteAsync([Required] [DisallowNull] TId id, CancellationToken cancellationToken) + public override async Task DeleteAsync([Required(AllowEmptyStrings = true)] [DisallowNull] TId id, CancellationToken cancellationToken) { return await base.DeleteAsync(id, cancellationToken); } /// [HttpDelete("{id}/relationships/{relationshipName}")] - public override async Task DeleteRelationshipAsync([Required] [DisallowNull] TId id, [Required] string relationshipName, - [Required] ISet rightResourceIds, CancellationToken cancellationToken) + public override async Task DeleteRelationshipAsync([Required(AllowEmptyStrings = true)] [DisallowNull] TId id, + [Required] string relationshipName, [Required] ISet rightResourceIds, CancellationToken cancellationToken) { return await base.DeleteRelationshipAsync(id, relationshipName, rightResourceIds, cancellationToken); } diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs b/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs index 168800b571..90fec3b9f3 100644 --- a/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs +++ b/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs @@ -14,8 +14,8 @@ namespace JsonApiDotNetCore.Controllers; /// public abstract class JsonApiOperationsController( IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, IOperationsProcessor processor, IJsonApiRequest request, - ITargetedFields targetedFields, IAtomicOperationFilter operationFilter) : BaseJsonApiOperationsController(options, resourceGraph, loggerFactory, processor, - request, targetedFields, operationFilter) + ITargetedFields targetedFields, IAtomicOperationFilter operationFilter) + : BaseJsonApiOperationsController(options, resourceGraph, loggerFactory, processor, request, targetedFields, operationFilter) { /// [HttpPost] diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiQueryController.cs b/src/JsonApiDotNetCore/Controllers/JsonApiQueryController.cs index fa101c2118..6db14e9fde 100644 --- a/src/JsonApiDotNetCore/Controllers/JsonApiQueryController.cs +++ b/src/JsonApiDotNetCore/Controllers/JsonApiQueryController.cs @@ -15,15 +15,7 @@ namespace JsonApiDotNetCore.Controllers; /// /// The resource identifier type. /// -public abstract class JsonApiQueryController : JsonApiController - where TResource : class, IIdentifiable -{ - /// - /// Creates an instance from a read-only service. - /// - protected JsonApiQueryController(IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, - IResourceQueryService queryService) - : base(options, resourceGraph, loggerFactory, queryService, queryService, queryService, queryService) - { - } -} +public abstract class JsonApiQueryController( + IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, IResourceQueryService queryService) + : JsonApiController(options, resourceGraph, loggerFactory, queryService, queryService, queryService, queryService) + where TResource : class, IIdentifiable; diff --git a/src/JsonApiDotNetCore/Controllers/PreserveEmptyStringAttribute.cs b/src/JsonApiDotNetCore/Controllers/PreserveEmptyStringAttribute.cs new file mode 100644 index 0000000000..d76f94ace1 --- /dev/null +++ b/src/JsonApiDotNetCore/Controllers/PreserveEmptyStringAttribute.cs @@ -0,0 +1,15 @@ +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; + +namespace JsonApiDotNetCore.Controllers; + +[PublicAPI] +[AttributeUsage(AttributeTargets.Parameter)] +public sealed class PreserveEmptyStringAttribute : DisplayFormatAttribute +{ + public PreserveEmptyStringAttribute() + { + // Workaround for https://github.com/dotnet/aspnetcore/issues/29948#issuecomment-1898216682 + ConvertEmptyStringToNull = false; + } +} diff --git a/src/JsonApiDotNetCore/Diagnostics/AspNetCodeTimerSession.cs b/src/JsonApiDotNetCore/Diagnostics/AspNetCodeTimerSession.cs index a42d734580..9b58dc43e7 100644 --- a/src/JsonApiDotNetCore/Diagnostics/AspNetCodeTimerSession.cs +++ b/src/JsonApiDotNetCore/Diagnostics/AspNetCodeTimerSession.cs @@ -37,14 +37,14 @@ public ICodeTimer CodeTimer public AspNetCodeTimerSession(IHttpContextAccessor httpContextAccessor) { - ArgumentGuard.NotNull(httpContextAccessor); + ArgumentNullException.ThrowIfNull(httpContextAccessor); _httpContextAccessor = httpContextAccessor; } public AspNetCodeTimerSession(HttpContext httpContext) { - ArgumentGuard.NotNull(httpContext); + ArgumentNullException.ThrowIfNull(httpContext); _httpContext = httpContext; } diff --git a/src/JsonApiDotNetCore/Diagnostics/CascadingCodeTimer.cs b/src/JsonApiDotNetCore/Diagnostics/CascadingCodeTimer.cs index 8fc75dad4e..48109b4c98 100644 --- a/src/JsonApiDotNetCore/Diagnostics/CascadingCodeTimer.cs +++ b/src/JsonApiDotNetCore/Diagnostics/CascadingCodeTimer.cs @@ -3,6 +3,8 @@ using System.Runtime.InteropServices; using System.Text; +#pragma warning disable CA2000 // Dispose objects before losing scope + namespace JsonApiDotNetCore.Diagnostics; /// @@ -65,7 +67,7 @@ private void Close(MeasureScope scope) _activeScopeStack.Pop(); - if (!_activeScopeStack.Any()) + if (_activeScopeStack.Count == 0) { _completedScopes.Add(scope); } @@ -92,7 +94,7 @@ private int GetPaddingLength() maxLength = Math.Max(maxLength, nextLength); } - if (_activeScopeStack.Any()) + if (_activeScopeStack.Count > 0) { MeasureScope scope = _activeScopeStack.Peek(); int nextLength = scope.GetPaddingLength(); @@ -109,7 +111,7 @@ private void WriteResult(StringBuilder builder, int paddingLength) scope.WriteResult(builder, 0, paddingLength); } - if (_activeScopeStack.Any()) + if (_activeScopeStack.Count > 0) { MeasureScope scope = _activeScopeStack.Peek(); scope.WriteResult(builder, 0, paddingLength); @@ -130,7 +132,7 @@ public void Dispose() private sealed class MeasureScope : IDisposable { private readonly CascadingCodeTimer _owner; - private readonly IList _children = new List(); + private readonly List _children = []; private readonly bool _excludeInRelativeCost; private readonly TimeSpan _startedAt; private TimeSpan? _stoppedAt; diff --git a/src/JsonApiDotNetCore/Diagnostics/CodeTimingSessionManager.cs b/src/JsonApiDotNetCore/Diagnostics/CodeTimingSessionManager.cs index 5a862409bc..adf642c3b8 100644 --- a/src/JsonApiDotNetCore/Diagnostics/CodeTimingSessionManager.cs +++ b/src/JsonApiDotNetCore/Diagnostics/CodeTimingSessionManager.cs @@ -10,7 +10,7 @@ namespace JsonApiDotNetCore.Diagnostics; /// public static class CodeTimingSessionManager { - public static readonly bool IsEnabled; + public static readonly bool IsEnabled = GetDefaultIsEnabled(); private static ICodeTimerSession? _session; public static ICodeTimer Current @@ -28,12 +28,12 @@ public static ICodeTimer Current } } - static CodeTimingSessionManager() + private static bool GetDefaultIsEnabled() { #if DEBUG - IsEnabled = !IsRunningInTest() && !IsRunningInBenchmark(); + return !IsRunningInTest() && !IsRunningInBenchmark() && !IsGeneratingOpenApiDocumentAtBuildTime(); #else - IsEnabled = false; + return false; #endif } @@ -52,6 +52,12 @@ private static bool IsRunningInBenchmark() return Assembly.GetEntryAssembly()?.GetName().Name == "Benchmarks"; } + // ReSharper disable once UnusedMember.Local + private static bool IsGeneratingOpenApiDocumentAtBuildTime() + { + return Environment.GetCommandLineArgs().Any(argument => argument.Contains("GetDocument.Insider")); + } + private static void AssertHasActiveSession() { if (_session == null) @@ -62,7 +68,7 @@ private static void AssertHasActiveSession() public static void Capture(ICodeTimerSession session) { - ArgumentGuard.NotNull(session); + ArgumentNullException.ThrowIfNull(session); AssertNoActiveSession(); diff --git a/src/JsonApiDotNetCore/Diagnostics/DefaultCodeTimerSession.cs b/src/JsonApiDotNetCore/Diagnostics/DefaultCodeTimerSession.cs index a1662095cb..6ee970711a 100644 --- a/src/JsonApiDotNetCore/Diagnostics/DefaultCodeTimerSession.cs +++ b/src/JsonApiDotNetCore/Diagnostics/DefaultCodeTimerSession.cs @@ -2,7 +2,7 @@ namespace JsonApiDotNetCore.Diagnostics; /// /// General code timing session management. Can be used with async/wait, but it cannot distinguish between concurrently running threads, so you'll need -/// to pass an instance through the entire call chain in that case. +/// to pass a instance through the entire call chain in that case. /// public sealed class DefaultCodeTimerSession : ICodeTimerSession { @@ -27,10 +27,7 @@ public DefaultCodeTimerSession() private void AssertNotDisposed() { - if (_codeTimerInContext.Value == null) - { - throw new ObjectDisposedException(nameof(DefaultCodeTimerSession)); - } + ObjectDisposedException.ThrowIf(_codeTimerInContext.Value == null, this); } public void Dispose() diff --git a/src/JsonApiDotNetCore/Errors/CannotClearRequiredRelationshipException.cs b/src/JsonApiDotNetCore/Errors/CannotClearRequiredRelationshipException.cs index 3ec95be11a..0a9db40c04 100644 --- a/src/JsonApiDotNetCore/Errors/CannotClearRequiredRelationshipException.cs +++ b/src/JsonApiDotNetCore/Errors/CannotClearRequiredRelationshipException.cs @@ -8,8 +8,8 @@ namespace JsonApiDotNetCore.Errors; /// The error that is thrown when a required relationship is cleared. /// [PublicAPI] -public sealed class CannotClearRequiredRelationshipException(string relationshipName, string resourceType) : JsonApiException( - new ErrorObject(HttpStatusCode.BadRequest) +public sealed class CannotClearRequiredRelationshipException(string relationshipName, string resourceType) + : JsonApiException(new ErrorObject(HttpStatusCode.BadRequest) { Title = "Failed to clear a required relationship.", Detail = $"The relationship '{relationshipName}' on resource type '{resourceType}' cannot be cleared because it is a required relationship." diff --git a/src/JsonApiDotNetCore/Errors/DuplicateLocalIdValueException.cs b/src/JsonApiDotNetCore/Errors/DuplicateLocalIdValueException.cs index 07ac377ae1..689529356b 100644 --- a/src/JsonApiDotNetCore/Errors/DuplicateLocalIdValueException.cs +++ b/src/JsonApiDotNetCore/Errors/DuplicateLocalIdValueException.cs @@ -8,8 +8,9 @@ namespace JsonApiDotNetCore.Errors; /// The error that is thrown when assigning a local ID that was already assigned in an earlier operation. /// [PublicAPI] -public sealed class DuplicateLocalIdValueException(string localId) : JsonApiException(new ErrorObject(HttpStatusCode.BadRequest) -{ - Title = "Another local ID with the same name is already defined at this point.", - Detail = $"Another local ID with name '{localId}' is already defined at this point." -}); +public sealed class DuplicateLocalIdValueException(string localId) + : JsonApiException(new ErrorObject(HttpStatusCode.BadRequest) + { + Title = "Another local ID with the same name is already defined at this point.", + Detail = $"Another local ID with name '{localId}' is already defined at this point." + }); diff --git a/src/JsonApiDotNetCore/Errors/FailedOperationException.cs b/src/JsonApiDotNetCore/Errors/FailedOperationException.cs index a6b970bcce..53bc2e1e5c 100644 --- a/src/JsonApiDotNetCore/Errors/FailedOperationException.cs +++ b/src/JsonApiDotNetCore/Errors/FailedOperationException.cs @@ -8,8 +8,8 @@ namespace JsonApiDotNetCore.Errors; /// The error that is thrown when an operation in an atomic:operations request failed to be processed for unknown reasons. /// [PublicAPI] -public sealed class FailedOperationException(int operationIndex, Exception innerException) : JsonApiException( - new ErrorObject(HttpStatusCode.InternalServerError) +public sealed class FailedOperationException(int operationIndex, Exception innerException) + : JsonApiException(new ErrorObject(HttpStatusCode.InternalServerError) { Title = "An unhandled error occurred while processing an operation in this request.", Detail = innerException.Message, diff --git a/src/JsonApiDotNetCore/Errors/IncompatibleLocalIdTypeException.cs b/src/JsonApiDotNetCore/Errors/IncompatibleLocalIdTypeException.cs index e893f04f00..0e6bfab8cb 100644 --- a/src/JsonApiDotNetCore/Errors/IncompatibleLocalIdTypeException.cs +++ b/src/JsonApiDotNetCore/Errors/IncompatibleLocalIdTypeException.cs @@ -8,8 +8,8 @@ namespace JsonApiDotNetCore.Errors; /// The error that is thrown when referencing a local ID that was assigned to a different resource type. /// [PublicAPI] -public sealed class IncompatibleLocalIdTypeException(string localId, string declaredType, string currentType) : JsonApiException( - new ErrorObject(HttpStatusCode.BadRequest) +public sealed class IncompatibleLocalIdTypeException(string localId, string declaredType, string currentType) + : JsonApiException(new ErrorObject(HttpStatusCode.BadRequest) { Title = "Incompatible type in Local ID usage.", Detail = $"Local ID '{localId}' belongs to resource type '{declaredType}' instead of '{currentType}'." diff --git a/src/JsonApiDotNetCore/Errors/InvalidConfigurationException.cs b/src/JsonApiDotNetCore/Errors/InvalidConfigurationException.cs index 0099e57c79..5e659bfc05 100644 --- a/src/JsonApiDotNetCore/Errors/InvalidConfigurationException.cs +++ b/src/JsonApiDotNetCore/Errors/InvalidConfigurationException.cs @@ -6,4 +6,5 @@ namespace JsonApiDotNetCore.Errors; /// The error that is thrown when configured usage of this library is invalid. /// [PublicAPI] -public sealed class InvalidConfigurationException(string message, Exception? innerException = null) : Exception(message, innerException); +public sealed class InvalidConfigurationException(string message, Exception? innerException = null) + : Exception(message, innerException); diff --git a/src/JsonApiDotNetCore/Errors/InvalidModelStateException.cs b/src/JsonApiDotNetCore/Errors/InvalidModelStateException.cs index 396694b50a..fc85156e57 100644 --- a/src/JsonApiDotNetCore/Errors/InvalidModelStateException.cs +++ b/src/JsonApiDotNetCore/Errors/InvalidModelStateException.cs @@ -17,15 +17,15 @@ namespace JsonApiDotNetCore.Errors; [PublicAPI] public sealed class InvalidModelStateException( IReadOnlyDictionary modelState, Type modelType, bool includeExceptionStackTraceInErrors, IResourceGraph resourceGraph, - Func? getCollectionElementTypeCallback = null) : JsonApiException(FromModelStateDictionary(modelState, modelType, resourceGraph, - includeExceptionStackTraceInErrors, getCollectionElementTypeCallback)) + Func? getCollectionElementTypeCallback = null) + : JsonApiException(FromModelStateDictionary(modelState, modelType, resourceGraph, includeExceptionStackTraceInErrors, getCollectionElementTypeCallback)) { - private static IEnumerable FromModelStateDictionary(IReadOnlyDictionary modelState, Type modelType, + private static List FromModelStateDictionary(IReadOnlyDictionary modelState, Type modelType, IResourceGraph resourceGraph, bool includeExceptionStackTraceInErrors, Func? getCollectionElementTypeCallback) { - ArgumentGuard.NotNull(modelState); - ArgumentGuard.NotNull(modelType); - ArgumentGuard.NotNull(resourceGraph); + ArgumentNullException.ThrowIfNull(modelState); + ArgumentNullException.ThrowIfNull(modelType); + ArgumentNullException.ThrowIfNull(resourceGraph); List errorObjects = []; @@ -186,7 +186,7 @@ private static ErrorObject FromModelError(ModelError modelError, string? sourceP Exception exception = modelError.Exception.Demystify(); string[] stackTraceLines = exception.ToString().Split(Environment.NewLine); - if (stackTraceLines.Any()) + if (stackTraceLines.Length > 0) { error.Meta ??= new Dictionary(); error.Meta["StackTrace"] = stackTraceLines; @@ -231,8 +231,8 @@ private abstract class ModelStateKeySegment protected ModelStateKeySegment(Type modelType, bool isInComplexType, string nextKey, string? sourcePointer, ModelStateKeySegment? parent, Func? getCollectionElementTypeCallback) { - ArgumentGuard.NotNull(modelType); - ArgumentGuard.NotNull(nextKey); + ArgumentNullException.ThrowIfNull(modelType); + ArgumentNullException.ThrowIfNull(nextKey); ModelType = modelType; IsInComplexType = isInComplexType; @@ -244,15 +244,15 @@ protected ModelStateKeySegment(Type modelType, bool isInComplexType, string next public ModelStateKeySegment? GetNextSegment(Type modelType, bool isInComplexType, string? sourcePointer) { - ArgumentGuard.NotNull(modelType); + ArgumentNullException.ThrowIfNull(modelType); - return _nextKey == string.Empty ? null : CreateSegment(modelType, _nextKey, isInComplexType, this, sourcePointer, GetCollectionElementTypeCallback); + return _nextKey.Length == 0 ? null : CreateSegment(modelType, _nextKey, isInComplexType, this, sourcePointer, GetCollectionElementTypeCallback); } public static ModelStateKeySegment Create(Type modelType, string key, Func? getCollectionElementTypeCallback) { - ArgumentGuard.NotNull(modelType); - ArgumentGuard.NotNull(key); + ArgumentNullException.ThrowIfNull(modelType); + ArgumentNullException.ThrowIfNull(key); return CreateSegment(modelType, key, false, null, null, getCollectionElementTypeCallback); } @@ -271,7 +271,7 @@ private static ModelStateKeySegment CreateSegment(Type modelType, string key, bo if (bracketCloseIndex != -1) { - segmentValue = key[1.. bracketCloseIndex]; + segmentValue = key[1..bracketCloseIndex]; int nextKeyStartIndex = key.Length > bracketCloseIndex + 1 && key[bracketCloseIndex + 1] == Dot ? bracketCloseIndex + 2 @@ -316,11 +316,9 @@ private static ModelStateKeySegment CreateSegment(Type modelType, string key, bo /// private sealed class ArrayIndexerSegment( int arrayIndex, Type modelType, bool isInComplexType, string nextKey, string? sourcePointer, ModelStateKeySegment? parent, - Func? getCollectionElementTypeCallback) : ModelStateKeySegment(modelType, isInComplexType, nextKey, sourcePointer, parent, - getCollectionElementTypeCallback) + Func? getCollectionElementTypeCallback) + : ModelStateKeySegment(modelType, isInComplexType, nextKey, sourcePointer, parent, getCollectionElementTypeCallback) { - private static readonly CollectionConverter CollectionConverter = new(); - public int ArrayIndex { get; } = arrayIndex; public Type GetCollectionElementType() @@ -333,7 +331,7 @@ private Type GetDeclaredCollectionElementType() { if (ModelType != typeof(string)) { - Type? elementType = CollectionConverter.FindCollectionElementType(ModelType); + Type? elementType = CollectionConverter.Instance.FindCollectionElementType(ModelType); if (elementType != null) { @@ -357,14 +355,14 @@ public PropertySegment(string propertyName, Type modelType, bool isInComplexType Func? getCollectionElementTypeCallback) : base(modelType, isInComplexType, nextKey, sourcePointer, parent, getCollectionElementTypeCallback) { - ArgumentGuard.NotNull(propertyName); + ArgumentNullException.ThrowIfNull(propertyName); PropertyName = propertyName; } public static string GetPublicNameForProperty(PropertyInfo property) { - ArgumentGuard.NotNull(property); + ArgumentNullException.ThrowIfNull(property); var jsonNameAttribute = property.GetCustomAttribute(true); return jsonNameAttribute?.Name ?? property.Name; diff --git a/src/JsonApiDotNetCore/Errors/InvalidQueryException.cs b/src/JsonApiDotNetCore/Errors/InvalidQueryException.cs index 76ebd91461..36ae294140 100644 --- a/src/JsonApiDotNetCore/Errors/InvalidQueryException.cs +++ b/src/JsonApiDotNetCore/Errors/InvalidQueryException.cs @@ -9,8 +9,9 @@ namespace JsonApiDotNetCore.Errors; /// The error that is thrown when translating a to Entity Framework Core fails. /// [PublicAPI] -public sealed class InvalidQueryException(string reason, Exception? innerException) : JsonApiException(new ErrorObject(HttpStatusCode.BadRequest) -{ - Title = reason, - Detail = innerException?.Message -}, innerException); +public sealed class InvalidQueryException(string reason, Exception? innerException) + : JsonApiException(new ErrorObject(HttpStatusCode.BadRequest) + { + Title = reason, + Detail = innerException?.Message + }, innerException); diff --git a/src/JsonApiDotNetCore/Errors/InvalidRequestBodyException.cs b/src/JsonApiDotNetCore/Errors/InvalidRequestBodyException.cs index 25297a4056..6e873eb388 100644 --- a/src/JsonApiDotNetCore/Errors/InvalidRequestBodyException.cs +++ b/src/JsonApiDotNetCore/Errors/InvalidRequestBodyException.cs @@ -2,6 +2,8 @@ using JetBrains.Annotations; using JsonApiDotNetCore.Serialization.Objects; +#pragma warning disable format + namespace JsonApiDotNetCore.Errors; /// @@ -10,20 +12,21 @@ namespace JsonApiDotNetCore.Errors; [PublicAPI] public sealed class InvalidRequestBodyException( string? requestBody, string? genericMessage, string? specificMessage, string? sourcePointer, HttpStatusCode? alternativeStatusCode = null, - Exception? innerException = null) : JsonApiException(new ErrorObject(alternativeStatusCode ?? HttpStatusCode.UnprocessableEntity) -{ - Title = genericMessage != null ? $"Failed to deserialize request body: {genericMessage}" : "Failed to deserialize request body.", - Detail = specificMessage, - Source = sourcePointer == null - ? null - : new ErrorSource - { - Pointer = sourcePointer - }, - Meta = string.IsNullOrEmpty(requestBody) - ? null - : new Dictionary - { - ["RequestBody"] = requestBody - } -}, innerException); + Exception? innerException = null) + : JsonApiException(new ErrorObject(alternativeStatusCode ?? HttpStatusCode.UnprocessableEntity) + { + Title = genericMessage != null ? $"Failed to deserialize request body: {genericMessage}" : "Failed to deserialize request body.", + Detail = specificMessage, + Source = sourcePointer == null + ? null + : new ErrorSource + { + Pointer = sourcePointer + }, + Meta = string.IsNullOrEmpty(requestBody) + ? null + : new Dictionary + { + ["RequestBody"] = requestBody + } + }, innerException); diff --git a/src/JsonApiDotNetCore/Errors/JsonApiException.cs b/src/JsonApiDotNetCore/Errors/JsonApiException.cs index 097b972089..b44b18d5a8 100644 --- a/src/JsonApiDotNetCore/Errors/JsonApiException.cs +++ b/src/JsonApiDotNetCore/Errors/JsonApiException.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using System.Text.Encodings.Web; using System.Text.Json; using System.Text.Json.Serialization; @@ -24,7 +25,7 @@ public class JsonApiException : Exception public JsonApiException(ErrorObject error, Exception? innerException = null) : base(null, innerException) { - ArgumentGuard.NotNull(error); + ArgumentNullException.ThrowIfNull(error); Errors = [error]; } @@ -32,15 +33,15 @@ public JsonApiException(ErrorObject error, Exception? innerException = null) public JsonApiException(IEnumerable errors, Exception? innerException = null) : base(null, innerException) { - IReadOnlyList? errorList = ToErrorList(errors); - ArgumentGuard.NotNullNorEmpty(errorList); + ReadOnlyCollection? errorCollection = ToCollection(errors); + ArgumentGuard.NotNullNorEmpty(errorCollection, nameof(errors)); - Errors = errorList; + Errors = errorCollection; } - private static IReadOnlyList? ToErrorList(IEnumerable? errors) + private static ReadOnlyCollection? ToCollection(IEnumerable? errors) { - return errors?.ToList(); + return errors?.ToArray().AsReadOnly(); } public string GetSummary() diff --git a/src/JsonApiDotNetCore/Errors/LocalIdSingleOperationException.cs b/src/JsonApiDotNetCore/Errors/LocalIdSingleOperationException.cs index e96f78672f..44ca7ecc4c 100644 --- a/src/JsonApiDotNetCore/Errors/LocalIdSingleOperationException.cs +++ b/src/JsonApiDotNetCore/Errors/LocalIdSingleOperationException.cs @@ -8,8 +8,9 @@ namespace JsonApiDotNetCore.Errors; /// The error that is thrown when assigning and referencing a local ID within the same operation. /// [PublicAPI] -public sealed class LocalIdSingleOperationException(string localId) : JsonApiException(new ErrorObject(HttpStatusCode.BadRequest) -{ - Title = "Local ID cannot be both defined and used within the same operation.", - Detail = $"Local ID '{localId}' cannot be both defined and used within the same operation." -}); +public sealed class LocalIdSingleOperationException(string localId) + : JsonApiException(new ErrorObject(HttpStatusCode.BadRequest) + { + Title = "Local ID cannot be both defined and used within the same operation.", + Detail = $"Local ID '{localId}' cannot be both defined and used within the same operation." + }); diff --git a/src/JsonApiDotNetCore/Errors/MissingResourceInRelationship.cs b/src/JsonApiDotNetCore/Errors/MissingResourceInRelationship.cs index 42082d6126..de38f61fcd 100644 --- a/src/JsonApiDotNetCore/Errors/MissingResourceInRelationship.cs +++ b/src/JsonApiDotNetCore/Errors/MissingResourceInRelationship.cs @@ -11,9 +11,9 @@ public sealed class MissingResourceInRelationship public MissingResourceInRelationship(string relationshipName, string resourceType, string resourceId) { - ArgumentGuard.NotNullNorEmpty(relationshipName); - ArgumentGuard.NotNullNorEmpty(resourceType); - ArgumentGuard.NotNullNorEmpty(resourceId); + ArgumentNullException.ThrowIfNull(relationshipName); + ArgumentNullException.ThrowIfNull(resourceType); + ArgumentNullException.ThrowIfNull(resourceId); RelationshipName = relationshipName; ResourceType = resourceType; diff --git a/src/JsonApiDotNetCore/Errors/MissingTransactionSupportException.cs b/src/JsonApiDotNetCore/Errors/MissingTransactionSupportException.cs index e682a5fac2..c8b182ad53 100644 --- a/src/JsonApiDotNetCore/Errors/MissingTransactionSupportException.cs +++ b/src/JsonApiDotNetCore/Errors/MissingTransactionSupportException.cs @@ -8,8 +8,9 @@ namespace JsonApiDotNetCore.Errors; /// The error that is thrown when accessing a repository that does not support transactions during an atomic:operations request. /// [PublicAPI] -public sealed class MissingTransactionSupportException(string resourceType) : JsonApiException(new ErrorObject(HttpStatusCode.UnprocessableEntity) -{ - Title = "Unsupported resource type in atomic:operations request.", - Detail = $"Operations on resources of type '{resourceType}' cannot be used because transaction support is unavailable." -}); +public sealed class MissingTransactionSupportException(string resourceType) + : JsonApiException(new ErrorObject(HttpStatusCode.UnprocessableEntity) + { + Title = "Unsupported resource type in atomic:operations request.", + Detail = $"Operations on resources of type '{resourceType}' cannot be used because transaction support is unavailable." + }); diff --git a/src/JsonApiDotNetCore/Errors/NonParticipatingTransactionException.cs b/src/JsonApiDotNetCore/Errors/NonParticipatingTransactionException.cs index b4855e27ff..24b8634f9e 100644 --- a/src/JsonApiDotNetCore/Errors/NonParticipatingTransactionException.cs +++ b/src/JsonApiDotNetCore/Errors/NonParticipatingTransactionException.cs @@ -8,8 +8,9 @@ namespace JsonApiDotNetCore.Errors; /// The error that is thrown when a repository does not participate in the overarching transaction during an atomic:operations request. /// [PublicAPI] -public sealed class NonParticipatingTransactionException() : JsonApiException(new ErrorObject(HttpStatusCode.UnprocessableEntity) -{ - Title = "Unsupported combination of resource types in atomic:operations request.", - Detail = "All operations need to participate in a single shared transaction, which is not the case for this request." -}); +public sealed class NonParticipatingTransactionException() + : JsonApiException(new ErrorObject(HttpStatusCode.UnprocessableEntity) + { + Title = "Unsupported combination of resource types in atomic:operations request.", + Detail = "All operations need to participate in a single shared transaction, which is not the case for this request." + }); diff --git a/src/JsonApiDotNetCore/Errors/RelationshipNotFoundException.cs b/src/JsonApiDotNetCore/Errors/RelationshipNotFoundException.cs index 11a72f803f..7fc5c92f66 100644 --- a/src/JsonApiDotNetCore/Errors/RelationshipNotFoundException.cs +++ b/src/JsonApiDotNetCore/Errors/RelationshipNotFoundException.cs @@ -8,8 +8,9 @@ namespace JsonApiDotNetCore.Errors; /// The error that is thrown when a relationship does not exist. /// [PublicAPI] -public sealed class RelationshipNotFoundException(string relationshipName, string resourceType) : JsonApiException(new ErrorObject(HttpStatusCode.NotFound) -{ - Title = "The requested relationship does not exist.", - Detail = $"Resource of type '{resourceType}' does not contain a relationship named '{relationshipName}'." -}); +public sealed class RelationshipNotFoundException(string relationshipName, string resourceType) + : JsonApiException(new ErrorObject(HttpStatusCode.NotFound) + { + Title = "The requested relationship does not exist.", + Detail = $"Resource of type '{resourceType}' does not contain a relationship named '{relationshipName}'." + }); diff --git a/src/JsonApiDotNetCore/Errors/ResourceAlreadyExistsException.cs b/src/JsonApiDotNetCore/Errors/ResourceAlreadyExistsException.cs index d2941422b9..518b59ef21 100644 --- a/src/JsonApiDotNetCore/Errors/ResourceAlreadyExistsException.cs +++ b/src/JsonApiDotNetCore/Errors/ResourceAlreadyExistsException.cs @@ -8,8 +8,9 @@ namespace JsonApiDotNetCore.Errors; /// The error that is thrown when creating a resource with an ID that already exists. /// [PublicAPI] -public sealed class ResourceAlreadyExistsException(string resourceId, string resourceType) : JsonApiException(new ErrorObject(HttpStatusCode.Conflict) -{ - Title = "Another resource with the specified ID already exists.", - Detail = $"Another resource of type '{resourceType}' with ID '{resourceId}' already exists." -}); +public sealed class ResourceAlreadyExistsException(string resourceId, string resourceType) + : JsonApiException(new ErrorObject(HttpStatusCode.Conflict) + { + Title = "Another resource with the specified ID already exists.", + Detail = $"Another resource of type '{resourceType}' with ID '{resourceId}' already exists." + }); diff --git a/src/JsonApiDotNetCore/Errors/ResourceNotFoundException.cs b/src/JsonApiDotNetCore/Errors/ResourceNotFoundException.cs index 5b2b2a829f..27ac99cafd 100644 --- a/src/JsonApiDotNetCore/Errors/ResourceNotFoundException.cs +++ b/src/JsonApiDotNetCore/Errors/ResourceNotFoundException.cs @@ -8,8 +8,9 @@ namespace JsonApiDotNetCore.Errors; /// The error that is thrown when a resource does not exist. /// [PublicAPI] -public sealed class ResourceNotFoundException(string resourceId, string resourceType) : JsonApiException(new ErrorObject(HttpStatusCode.NotFound) -{ - Title = "The requested resource does not exist.", - Detail = $"Resource of type '{resourceType}' with ID '{resourceId}' does not exist." -}); +public sealed class ResourceNotFoundException(string resourceId, string resourceType) + : JsonApiException(new ErrorObject(HttpStatusCode.NotFound) + { + Title = "The requested resource does not exist.", + Detail = $"Resource of type '{resourceType}' with ID '{resourceId}' does not exist." + }); diff --git a/src/JsonApiDotNetCore/Errors/RouteNotAvailableException.cs b/src/JsonApiDotNetCore/Errors/RouteNotAvailableException.cs index 0bd1a3debd..d04d2c599b 100644 --- a/src/JsonApiDotNetCore/Errors/RouteNotAvailableException.cs +++ b/src/JsonApiDotNetCore/Errors/RouteNotAvailableException.cs @@ -8,11 +8,12 @@ namespace JsonApiDotNetCore.Errors; /// The error that is thrown when a request is received for an HTTP route that is not exposed. /// [PublicAPI] -public sealed class RouteNotAvailableException(HttpMethod method, string route) : JsonApiException(new ErrorObject(HttpStatusCode.Forbidden) -{ - Title = "The requested endpoint is not accessible.", - Detail = $"Endpoint '{route}' is not accessible for {method} requests." -}) +public sealed class RouteNotAvailableException(HttpMethod method, string route) + : JsonApiException(new ErrorObject(HttpStatusCode.Forbidden) + { + Title = "The requested endpoint is not accessible.", + Detail = $"Endpoint '{route}' is not accessible for {method} requests." + }) { public HttpMethod Method { get; } = method; } diff --git a/src/JsonApiDotNetCore/Errors/UnknownLocalIdValueException.cs b/src/JsonApiDotNetCore/Errors/UnknownLocalIdValueException.cs index 4cd5e3d0de..023f577912 100644 --- a/src/JsonApiDotNetCore/Errors/UnknownLocalIdValueException.cs +++ b/src/JsonApiDotNetCore/Errors/UnknownLocalIdValueException.cs @@ -8,8 +8,9 @@ namespace JsonApiDotNetCore.Errors; /// The error that is thrown when referencing a local ID that hasn't been assigned. /// [PublicAPI] -public sealed class UnknownLocalIdValueException(string localId) : JsonApiException(new ErrorObject(HttpStatusCode.BadRequest) -{ - Title = "Server-generated value for local ID is not available at this point.", - Detail = $"Server-generated value for local ID '{localId}' is not available at this point." -}); +public sealed class UnknownLocalIdValueException(string localId) + : JsonApiException(new ErrorObject(HttpStatusCode.BadRequest) + { + Title = "Server-generated value for local ID is not available at this point.", + Detail = $"Server-generated value for local ID '{localId}' is not available at this point." + }); diff --git a/src/JsonApiDotNetCore/Errors/UnsuccessfulActionResultException.cs b/src/JsonApiDotNetCore/Errors/UnsuccessfulActionResultException.cs index b5ab3859cc..9e8083f7dc 100644 --- a/src/JsonApiDotNetCore/Errors/UnsuccessfulActionResultException.cs +++ b/src/JsonApiDotNetCore/Errors/UnsuccessfulActionResultException.cs @@ -27,11 +27,11 @@ public UnsuccessfulActionResultException(ProblemDetails problemDetails) private static IEnumerable ToErrorObjects(ProblemDetails problemDetails) { - ArgumentGuard.NotNull(problemDetails); + ArgumentNullException.ThrowIfNull(problemDetails); HttpStatusCode status = problemDetails.Status != null ? (HttpStatusCode)problemDetails.Status.Value : HttpStatusCode.InternalServerError; - if (problemDetails is HttpValidationProblemDetails validationProblemDetails && validationProblemDetails.Errors.Any()) + if (problemDetails is HttpValidationProblemDetails { Errors.Count: > 0 } validationProblemDetails) { foreach (string errorMessage in validationProblemDetails.Errors.SelectMany(pair => pair.Value)) { diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj index 0f395511a7..1c1ba7ab7f 100644 --- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj +++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj @@ -1,6 +1,6 @@ - net8.0;net6.0 + net8.0 true true @@ -8,7 +8,6 @@ - $(JsonApiDotNetCoreVersionPrefix) jsonapidotnetcore;jsonapi;json:api;dotnet;asp.net;rest;web-api A framework for building JSON:API compliant REST APIs using ASP.NET and Entity Framework Core. Includes support for Atomic Operations. The ultimate goal of this library is to eliminate as much boilerplate as possible by offering out-of-the-box features such as sorting, filtering and pagination. You just need to focus on defining the resources and implementing your custom business logic. This library has been designed around dependency injection making extensibility incredibly easy. json-api-dotnet @@ -19,7 +18,6 @@ package-icon.png PackageReadme.md true - true embedded @@ -42,7 +40,6 @@ - diff --git a/src/JsonApiDotNetCore/Middleware/AlwaysEnabledJsonApiEndpointFilter.cs b/src/JsonApiDotNetCore/Middleware/AlwaysEnabledJsonApiEndpointFilter.cs new file mode 100644 index 0000000000..c3918d7462 --- /dev/null +++ b/src/JsonApiDotNetCore/Middleware/AlwaysEnabledJsonApiEndpointFilter.cs @@ -0,0 +1,13 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; + +namespace JsonApiDotNetCore.Middleware; + +internal sealed class AlwaysEnabledJsonApiEndpointFilter : IJsonApiEndpointFilter +{ + /// + public bool IsEnabled(ResourceType resourceType, JsonApiEndpoints endpoint) + { + return true; + } +} diff --git a/src/JsonApiDotNetCore/Middleware/AsyncConvertEmptyActionResultFilter.cs b/src/JsonApiDotNetCore/Middleware/AsyncConvertEmptyActionResultFilter.cs index a895c20ba4..440d3e69ea 100644 --- a/src/JsonApiDotNetCore/Middleware/AsyncConvertEmptyActionResultFilter.cs +++ b/src/JsonApiDotNetCore/Middleware/AsyncConvertEmptyActionResultFilter.cs @@ -10,8 +10,8 @@ public sealed class AsyncConvertEmptyActionResultFilter : IAsyncConvertEmptyActi /// public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next) { - ArgumentGuard.NotNull(context); - ArgumentGuard.NotNull(next); + ArgumentNullException.ThrowIfNull(context); + ArgumentNullException.ThrowIfNull(next); if (context.HttpContext.IsJsonApiRequest()) { diff --git a/src/JsonApiDotNetCore/Middleware/AsyncJsonApiExceptionFilter.cs b/src/JsonApiDotNetCore/Middleware/AsyncJsonApiExceptionFilter.cs index 45a0b96891..915747de8b 100644 --- a/src/JsonApiDotNetCore/Middleware/AsyncJsonApiExceptionFilter.cs +++ b/src/JsonApiDotNetCore/Middleware/AsyncJsonApiExceptionFilter.cs @@ -13,7 +13,7 @@ public sealed class AsyncJsonApiExceptionFilter : IAsyncJsonApiExceptionFilter public AsyncJsonApiExceptionFilter(IExceptionHandler exceptionHandler) { - ArgumentGuard.NotNull(exceptionHandler); + ArgumentNullException.ThrowIfNull(exceptionHandler); _exceptionHandler = exceptionHandler; } @@ -21,7 +21,7 @@ public AsyncJsonApiExceptionFilter(IExceptionHandler exceptionHandler) /// public Task OnExceptionAsync(ExceptionContext context) { - ArgumentGuard.NotNull(context); + ArgumentNullException.ThrowIfNull(context); if (context.HttpContext.IsJsonApiRequest()) { diff --git a/src/JsonApiDotNetCore/Middleware/AsyncQueryStringActionFilter.cs b/src/JsonApiDotNetCore/Middleware/AsyncQueryStringActionFilter.cs index 6c394a531f..e832b4693a 100644 --- a/src/JsonApiDotNetCore/Middleware/AsyncQueryStringActionFilter.cs +++ b/src/JsonApiDotNetCore/Middleware/AsyncQueryStringActionFilter.cs @@ -12,7 +12,7 @@ public sealed class AsyncQueryStringActionFilter : IAsyncQueryStringActionFilter public AsyncQueryStringActionFilter(IQueryStringReader queryStringReader) { - ArgumentGuard.NotNull(queryStringReader); + ArgumentNullException.ThrowIfNull(queryStringReader); _queryStringReader = queryStringReader; } @@ -20,8 +20,8 @@ public AsyncQueryStringActionFilter(IQueryStringReader queryStringReader) /// public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { - ArgumentGuard.NotNull(context); - ArgumentGuard.NotNull(next); + ArgumentNullException.ThrowIfNull(context); + ArgumentNullException.ThrowIfNull(next); if (context.HttpContext.IsJsonApiRequest()) { diff --git a/src/JsonApiDotNetCore/Middleware/ExceptionHandler.cs b/src/JsonApiDotNetCore/Middleware/ExceptionHandler.cs index 816c5ffbb7..44e1b384ef 100644 --- a/src/JsonApiDotNetCore/Middleware/ExceptionHandler.cs +++ b/src/JsonApiDotNetCore/Middleware/ExceptionHandler.cs @@ -10,15 +10,15 @@ namespace JsonApiDotNetCore.Middleware; /// [PublicAPI] -public class ExceptionHandler : IExceptionHandler +public partial class ExceptionHandler : IExceptionHandler { private readonly IJsonApiOptions _options; private readonly ILogger _logger; public ExceptionHandler(ILoggerFactory loggerFactory, IJsonApiOptions options) { - ArgumentGuard.NotNull(loggerFactory); - ArgumentGuard.NotNull(options); + ArgumentNullException.ThrowIfNull(loggerFactory); + ArgumentNullException.ThrowIfNull(options); _options = options; _logger = loggerFactory.CreateLogger(); @@ -26,7 +26,7 @@ public ExceptionHandler(ILoggerFactory loggerFactory, IJsonApiOptions options) public IReadOnlyList HandleException(Exception exception) { - ArgumentGuard.NotNull(exception); + ArgumentNullException.ThrowIfNull(exception); Exception demystified = exception.Demystify(); @@ -40,12 +40,12 @@ private void LogException(Exception exception) LogLevel level = GetLogLevel(exception); string message = GetLogMessage(exception); - _logger.Log(level, exception, message); + LogException(level, exception, message); } protected virtual LogLevel GetLogLevel(Exception exception) { - ArgumentGuard.NotNull(exception); + ArgumentNullException.ThrowIfNull(exception); if (exception is OperationCanceledException) { @@ -62,33 +62,33 @@ protected virtual LogLevel GetLogLevel(Exception exception) protected virtual string GetLogMessage(Exception exception) { - ArgumentGuard.NotNull(exception); + ArgumentNullException.ThrowIfNull(exception); return exception is JsonApiException jsonApiException ? jsonApiException.GetSummary() : exception.Message; } protected virtual IReadOnlyList CreateErrorResponse(Exception exception) { - ArgumentGuard.NotNull(exception); + ArgumentNullException.ThrowIfNull(exception); IReadOnlyList errors = exception switch { JsonApiException jsonApiException => jsonApiException.Errors, - OperationCanceledException => - [ + OperationCanceledException => new[] + { new ErrorObject((HttpStatusCode)499) { Title = "Request execution was canceled." } - ], - _ => - [ + }.AsReadOnly(), + _ => new[] + { new ErrorObject(HttpStatusCode.InternalServerError) { Title = "An unhandled error occurred while processing this request.", Detail = exception.Message } - ] + }.AsReadOnly() }; if (_options.IncludeExceptionStackTraceInErrors && exception is not InvalidModelStateException) @@ -103,7 +103,7 @@ private void IncludeStackTraces(Exception exception, IReadOnlyList { string[] stackTraceLines = exception.ToString().Split(Environment.NewLine); - if (stackTraceLines.Any()) + if (stackTraceLines.Length > 0) { foreach (ErrorObject error in errors) { @@ -112,4 +112,7 @@ private void IncludeStackTraces(Exception exception, IReadOnlyList } } } + + [LoggerMessage(Message = "{Message}")] + private partial void LogException(LogLevel level, Exception exception, string message); } diff --git a/src/JsonApiDotNetCore/Middleware/HeaderConstants.cs b/src/JsonApiDotNetCore/Middleware/HeaderConstants.cs index 2e223e7fea..05ddc69a6b 100644 --- a/src/JsonApiDotNetCore/Middleware/HeaderConstants.cs +++ b/src/JsonApiDotNetCore/Middleware/HeaderConstants.cs @@ -7,7 +7,12 @@ namespace JsonApiDotNetCore.Middleware; [PublicAPI] public static class HeaderConstants { + [Obsolete($"Use {nameof(JsonApiMediaType)}.{nameof(JsonApiMediaType.Default)}.ToString() instead.")] public const string MediaType = "application/vnd.api+json"; + + [Obsolete($"Use {nameof(JsonApiMediaType)}.{nameof(JsonApiMediaType.AtomicOperations)}.ToString() instead.")] public const string AtomicOperationsMediaType = $"{MediaType}; ext=\"https://jsonapi.org/ext/atomic\""; - public const string RelaxedAtomicOperationsMediaType = $"{MediaType}; ext=atomic-operations"; + + [Obsolete($"Use {nameof(JsonApiMediaType)}.{nameof(JsonApiMediaType.RelaxedAtomicOperations)}.ToString() instead.")] + public const string RelaxedAtomicOperationsMediaType = $"{MediaType}; ext=atomic"; } diff --git a/src/JsonApiDotNetCore/Middleware/HttpContextExtensions.cs b/src/JsonApiDotNetCore/Middleware/HttpContextExtensions.cs index a675aeeaff..85de6e92fb 100644 --- a/src/JsonApiDotNetCore/Middleware/HttpContextExtensions.cs +++ b/src/JsonApiDotNetCore/Middleware/HttpContextExtensions.cs @@ -13,7 +13,7 @@ public static class HttpContextExtensions /// public static bool IsJsonApiRequest(this HttpContext httpContext) { - ArgumentGuard.NotNull(httpContext); + ArgumentNullException.ThrowIfNull(httpContext); string? value = httpContext.Items[IsJsonApiRequestKey] as string; return value == bool.TrueString; @@ -21,7 +21,7 @@ public static bool IsJsonApiRequest(this HttpContext httpContext) internal static void RegisterJsonApiRequest(this HttpContext httpContext) { - ArgumentGuard.NotNull(httpContext); + ArgumentNullException.ThrowIfNull(httpContext); httpContext.Items[IsJsonApiRequestKey] = bool.TrueString; } diff --git a/src/JsonApiDotNetCore/Middleware/HttpMethodAttributeExtensions.cs b/src/JsonApiDotNetCore/Middleware/HttpMethodAttributeExtensions.cs new file mode 100644 index 0000000000..b85e2f53ae --- /dev/null +++ b/src/JsonApiDotNetCore/Middleware/HttpMethodAttributeExtensions.cs @@ -0,0 +1,56 @@ +using JsonApiDotNetCore.Controllers; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Routing; + +namespace JsonApiDotNetCore.Middleware; + +internal static class HttpMethodAttributeExtensions +{ + private const string IdTemplate = "{id}"; + private const string RelationshipNameTemplate = "{relationshipName}"; + private const string SecondaryEndpointTemplate = $"{IdTemplate}/{RelationshipNameTemplate}"; + private const string RelationshipEndpointTemplate = $"{IdTemplate}/relationships/{RelationshipNameTemplate}"; + + public static JsonApiEndpoints GetJsonApiEndpoint(this IEnumerable httpMethods) + { + ArgumentNullException.ThrowIfNull(httpMethods); + + HttpMethodAttribute[] nonHeadAttributes = httpMethods.Where(attribute => attribute is not HttpHeadAttribute).ToArray(); + + return nonHeadAttributes.Length == 1 ? ResolveJsonApiEndpoint(nonHeadAttributes[0]) : JsonApiEndpoints.None; + } + + private static JsonApiEndpoints ResolveJsonApiEndpoint(HttpMethodAttribute httpMethod) + { + return httpMethod switch + { + HttpGetAttribute httpGet => httpGet.Template switch + { + null => JsonApiEndpoints.GetCollection, + IdTemplate => JsonApiEndpoints.GetSingle, + SecondaryEndpointTemplate => JsonApiEndpoints.GetSecondary, + RelationshipEndpointTemplate => JsonApiEndpoints.GetRelationship, + _ => JsonApiEndpoints.None + }, + HttpPostAttribute httpPost => httpPost.Template switch + { + null => JsonApiEndpoints.Post, + RelationshipEndpointTemplate => JsonApiEndpoints.PostRelationship, + _ => JsonApiEndpoints.None + }, + HttpPatchAttribute httpPatch => httpPatch.Template switch + { + IdTemplate => JsonApiEndpoints.Patch, + RelationshipEndpointTemplate => JsonApiEndpoints.PatchRelationship, + _ => JsonApiEndpoints.None + }, + HttpDeleteAttribute httpDelete => httpDelete.Template switch + { + IdTemplate => JsonApiEndpoints.Delete, + RelationshipEndpointTemplate => JsonApiEndpoints.DeleteRelationship, + _ => JsonApiEndpoints.None + }, + _ => JsonApiEndpoints.None + }; + } +} diff --git a/src/JsonApiDotNetCore/Middleware/IJsonApiContentNegotiator.cs b/src/JsonApiDotNetCore/Middleware/IJsonApiContentNegotiator.cs new file mode 100644 index 0000000000..f80c910266 --- /dev/null +++ b/src/JsonApiDotNetCore/Middleware/IJsonApiContentNegotiator.cs @@ -0,0 +1,16 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Errors; + +namespace JsonApiDotNetCore.Middleware; + +/// +/// Performs content negotiation for JSON:API requests. +/// +public interface IJsonApiContentNegotiator +{ + /// + /// Validates the Content-Type and Accept HTTP headers from the incoming request. Throws a if unsupported. Otherwise, + /// returns the list of negotiated JSON:API extensions, which should always be a subset of . + /// + IReadOnlySet Negotiate(); +} diff --git a/src/JsonApiDotNetCore/Middleware/IJsonApiEndpointFilter.cs b/src/JsonApiDotNetCore/Middleware/IJsonApiEndpointFilter.cs new file mode 100644 index 0000000000..6dbf81bce3 --- /dev/null +++ b/src/JsonApiDotNetCore/Middleware/IJsonApiEndpointFilter.cs @@ -0,0 +1,24 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; + +namespace JsonApiDotNetCore.Middleware; + +/// +/// Enables to remove JSON:API controller action methods at startup. For atomic:operation requests, see . +/// +[PublicAPI] +public interface IJsonApiEndpointFilter +{ + /// + /// Determines whether to remove the associated controller action method. + /// + /// + /// The primary resource type of the endpoint. + /// + /// + /// The JSON:API endpoint. Despite being a enum, a single value is always passed here. + /// + bool IsEnabled(ResourceType resourceType, JsonApiEndpoints endpoint); +} diff --git a/src/JsonApiDotNetCore/Middleware/IJsonApiRequest.cs b/src/JsonApiDotNetCore/Middleware/IJsonApiRequest.cs index 1d66bf517f..959c89d66f 100644 --- a/src/JsonApiDotNetCore/Middleware/IJsonApiRequest.cs +++ b/src/JsonApiDotNetCore/Middleware/IJsonApiRequest.cs @@ -60,6 +60,11 @@ public interface IJsonApiRequest /// string? TransactionId { get; } + /// + /// The JSON:API extensions enabled for the current request. This is always a subset of . + /// + IReadOnlySet Extensions { get; } + /// /// Performs a shallow copy. /// diff --git a/src/JsonApiDotNetCore/Middleware/JsonApiContentNegotiator.cs b/src/JsonApiDotNetCore/Middleware/JsonApiContentNegotiator.cs new file mode 100644 index 0000000000..a9806129f8 --- /dev/null +++ b/src/JsonApiDotNetCore/Middleware/JsonApiContentNegotiator.cs @@ -0,0 +1,241 @@ +using System.Net; +using JetBrains.Annotations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Errors; +using JsonApiDotNetCore.Serialization.Objects; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Routing; + +namespace JsonApiDotNetCore.Middleware; + +/// +[PublicAPI] +public class JsonApiContentNegotiator : IJsonApiContentNegotiator +{ + private readonly IJsonApiOptions _options; + private readonly IHttpContextAccessor _httpContextAccessor; + + private HttpContext HttpContext + { + get + { + if (_httpContextAccessor.HttpContext == null) + { + throw new InvalidOperationException("An active HTTP request is required."); + } + + return _httpContextAccessor.HttpContext; + } + } + + public JsonApiContentNegotiator(IJsonApiOptions options, IHttpContextAccessor httpContextAccessor) + { + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(httpContextAccessor); + + _options = options; + _httpContextAccessor = httpContextAccessor; + } + + /// + public IReadOnlySet Negotiate() + { + IReadOnlyList possibleMediaTypes = GetPossibleMediaTypes(); + + JsonApiMediaType? requestMediaType = ValidateContentType(possibleMediaTypes); + return ValidateAcceptHeader(possibleMediaTypes, requestMediaType); + } + + private JsonApiMediaType? ValidateContentType(IReadOnlyList possibleMediaTypes) + { + if (HttpContext.Request.ContentType == null) + { + if (HttpContext.Request.ContentLength > 0) + { + throw CreateContentTypeError(possibleMediaTypes); + } + + return null; + } + + JsonApiMediaType? mediaType = JsonApiMediaType.TryParseContentTypeHeaderValue(HttpContext.Request.ContentType); + + if (mediaType == null || !possibleMediaTypes.Contains(mediaType)) + { + throw CreateContentTypeError(possibleMediaTypes); + } + + return mediaType; + } + + private IReadOnlySet ValidateAcceptHeader(IReadOnlyList possibleMediaTypes, JsonApiMediaType? requestMediaType) + { + string[] acceptHeaderValues = HttpContext.Request.Headers.GetCommaSeparatedValues("Accept"); + JsonApiMediaType? bestMatch = null; + + if (acceptHeaderValues.Length == 0) + { + bestMatch = GetDefaultMediaType(possibleMediaTypes, requestMediaType); + } + else + { + decimal bestQualityFactor = 0m; + + foreach (string acceptHeaderValue in acceptHeaderValues) + { + (JsonApiMediaType MediaType, decimal QualityFactor)? result = JsonApiMediaType.TryParseAcceptHeaderValue(acceptHeaderValue); + + if (result != null) + { + if (result.Value.MediaType.Equals(requestMediaType) && possibleMediaTypes.Contains(requestMediaType)) + { + // Content-Type always wins over other candidates, because JsonApiDotNetCore doesn't support + // different extension sets for the request and response body. + bestMatch = requestMediaType; + break; + } + + bool isBetterMatch = false; + int? currentIndex = null; + + if (bestMatch == null) + { + isBetterMatch = true; + } + else if (result.Value.QualityFactor > bestQualityFactor) + { + isBetterMatch = true; + } + else if (result.Value.QualityFactor == bestQualityFactor) + { + if (result.Value.MediaType.Extensions.Count > bestMatch.Extensions.Count) + { + isBetterMatch = true; + } + else if (result.Value.MediaType.Extensions.Count == bestMatch.Extensions.Count) + { + int bestIndex = possibleMediaTypes.FindIndex(bestMatch); + currentIndex = possibleMediaTypes.FindIndex(result.Value.MediaType); + + if (currentIndex != -1 && currentIndex < bestIndex) + { + isBetterMatch = true; + } + } + } + + if (isBetterMatch) + { + bool existsInPossibleMediaTypes = currentIndex >= 0 || possibleMediaTypes.Contains(result.Value.MediaType); + + if (existsInPossibleMediaTypes) + { + bestMatch = result.Value.MediaType; + bestQualityFactor = result.Value.QualityFactor; + } + } + } + } + } + + if (bestMatch == null) + { + throw CreateAcceptHeaderError(possibleMediaTypes); + } + + if (requestMediaType != null && !bestMatch.Equals(requestMediaType)) + { + throw CreateAcceptHeaderError(possibleMediaTypes); + } + + return bestMatch.Extensions; + } + + /// + /// Returns the JSON:API media type (possibly including extensions) to use when no Accept header was sent. + /// + /// + /// The media types returned from . + /// + /// + /// The media type from in the Content-Type header. + /// + /// + /// The default media type to use, or null if not available. + /// + protected virtual JsonApiMediaType? GetDefaultMediaType(IReadOnlyList possibleMediaTypes, JsonApiMediaType? requestMediaType) + { + return possibleMediaTypes.Contains(JsonApiMediaType.Default) ? JsonApiMediaType.Default : null; + } + + /// + /// Gets the list of possible combinations of JSON:API extensions that are available at the current endpoint. The set of extensions in the request body + /// must always be the same as in the response body. + /// + /// + /// Override this method to add support for custom JSON:API extensions. Implementations should take into + /// account. During content negotiation, the first compatible entry with the highest number of extensions is preferred, but beware that clients can + /// overrule this using quality factors in an Accept header. + /// + protected virtual IReadOnlyList GetPossibleMediaTypes() + { + List mediaTypes = []; + + // Relaxed entries come after JSON:API compliant entries, which makes them less likely to be selected. + + if (IsOperationsEndpoint()) + { + if (_options.Extensions.Contains(JsonApiMediaTypeExtension.AtomicOperations)) + { + mediaTypes.Add(JsonApiMediaType.AtomicOperations); + } + + if (_options.Extensions.Contains(JsonApiMediaTypeExtension.RelaxedAtomicOperations)) + { + mediaTypes.Add(JsonApiMediaType.RelaxedAtomicOperations); + } + } + else + { + mediaTypes.Add(JsonApiMediaType.Default); + } + + return mediaTypes.AsReadOnly(); + } + + protected bool IsOperationsEndpoint() + { + RouteValueDictionary routeValues = HttpContext.GetRouteData().Values; + return JsonApiMiddleware.IsRouteForOperations(routeValues); + } + + private JsonApiException CreateContentTypeError(IReadOnlyList possibleMediaTypes) + { + string allowedValues = string.Join(" or ", possibleMediaTypes.Select(mediaType => $"'{mediaType}'")); + + return new JsonApiException(new ErrorObject(HttpStatusCode.UnsupportedMediaType) + { + Title = "The specified Content-Type header value is not supported.", + Detail = $"Use {allowedValues} instead of '{HttpContext.Request.ContentType}' for the Content-Type header value.", + Source = new ErrorSource + { + Header = "Content-Type" + } + }); + } + + private static JsonApiException CreateAcceptHeaderError(IReadOnlyList possibleMediaTypes) + { + string allowedValues = string.Join(" or ", possibleMediaTypes.Select(mediaType => $"'{mediaType}'")); + + return new JsonApiException(new ErrorObject(HttpStatusCode.NotAcceptable) + { + Title = "The specified Accept header value does not contain any supported media types.", + Detail = $"Include {allowedValues} in the Accept header values.", + Source = new ErrorSource + { + Header = "Accept" + } + }); + } +} diff --git a/src/JsonApiDotNetCore/Middleware/JsonApiInputFormatter.cs b/src/JsonApiDotNetCore/Middleware/JsonApiInputFormatter.cs index 9988d0dcaf..008d5fd6dd 100644 --- a/src/JsonApiDotNetCore/Middleware/JsonApiInputFormatter.cs +++ b/src/JsonApiDotNetCore/Middleware/JsonApiInputFormatter.cs @@ -10,7 +10,7 @@ public sealed class JsonApiInputFormatter : IJsonApiInputFormatter /// public bool CanRead(InputFormatterContext context) { - ArgumentGuard.NotNull(context); + ArgumentNullException.ThrowIfNull(context); return context.HttpContext.IsJsonApiRequest(); } @@ -18,7 +18,7 @@ public bool CanRead(InputFormatterContext context) /// public async Task ReadAsync(InputFormatterContext context) { - ArgumentGuard.NotNull(context); + ArgumentNullException.ThrowIfNull(context); var reader = context.HttpContext.RequestServices.GetRequiredService(); diff --git a/src/JsonApiDotNetCore/Middleware/JsonApiMediaType.cs b/src/JsonApiDotNetCore/Middleware/JsonApiMediaType.cs new file mode 100644 index 0000000000..cfb2cb8b07 --- /dev/null +++ b/src/JsonApiDotNetCore/Middleware/JsonApiMediaType.cs @@ -0,0 +1,188 @@ +using JetBrains.Annotations; +using Microsoft.Extensions.Primitives; +using Microsoft.Net.Http.Headers; + +namespace JsonApiDotNetCore.Middleware; + +/// +/// Represents the JSON:API media type (application/vnd.api+json) with an optional set of extensions. +/// +[PublicAPI] +public sealed class JsonApiMediaType : IEquatable +{ + private static readonly StringSegment BaseMediaTypeSegment = new("application/vnd.api+json"); + private static readonly StringSegment ExtSegment = new("ext"); + private static readonly StringSegment QualitySegment = new("q"); + + /// + /// Gets the JSON:API media type without any extensions. + /// + public static readonly JsonApiMediaType Default = new([]); + + /// + /// Gets the JSON:API media type with the "https://jsonapi.org/ext/atomic" extension. + /// + public static readonly JsonApiMediaType AtomicOperations = new([JsonApiMediaTypeExtension.AtomicOperations]); + + /// + /// Gets the JSON:API media type with the "atomic" extension. + /// + public static readonly JsonApiMediaType RelaxedAtomicOperations = new([JsonApiMediaTypeExtension.RelaxedAtomicOperations]); + + public IReadOnlySet Extensions { get; } + + public JsonApiMediaType(IReadOnlySet extensions) + { + ArgumentNullException.ThrowIfNull(extensions); + + Extensions = extensions; + } + + public JsonApiMediaType(IEnumerable extensions) + { + ArgumentNullException.ThrowIfNull(extensions); + + Extensions = extensions.ToHashSet().AsReadOnly(); + } + + internal static JsonApiMediaType? TryParseContentTypeHeaderValue(string value) + { + (JsonApiMediaType MediaType, decimal QualityFactor)? result = TryParse(value, false, false); + return result?.MediaType; + } + + internal static (JsonApiMediaType MediaType, decimal QualityFactor)? TryParseAcceptHeaderValue(string value) + { + return TryParse(value, true, true); + } + + private static (JsonApiMediaType MediaType, decimal QualityFactor)? TryParse(string value, bool allowSuperset, bool allowQualityFactor) + { + // Parameter names are case-insensitive, according to https://datatracker.ietf.org/doc/html/rfc7231#section-3.1.1.1. + // But JSON:API doesn't define case-insensitive for the "ext" parameter value. + + if (MediaTypeHeaderValue.TryParse(value, out MediaTypeHeaderValue? headerValue)) + { + bool isBaseMatch = allowSuperset + ? headerValue.MatchesMediaType(BaseMediaTypeSegment) + : BaseMediaTypeSegment.Equals(headerValue.MediaType, StringComparison.OrdinalIgnoreCase); + + if (isBaseMatch) + { + HashSet extensions = []; + + decimal qualityFactor = 1.0m; + + foreach (NameValueHeaderValue parameter in headerValue.Parameters) + { + if (allowQualityFactor && parameter.Name.Equals(QualitySegment, StringComparison.OrdinalIgnoreCase) && + decimal.TryParse(parameter.Value, out decimal qualityValue)) + { + qualityFactor = qualityValue; + continue; + } + + if (!parameter.Name.Equals(ExtSegment, StringComparison.OrdinalIgnoreCase)) + { + return null; + } + + ParseExtensions(parameter, extensions); + } + + return (new JsonApiMediaType(extensions), qualityFactor); + } + } + + return null; + } + + private static void ParseExtensions(NameValueHeaderValue parameter, HashSet extensions) + { + string parameterValue = parameter.GetUnescapedValue().ToString(); + + foreach (string extValue in parameterValue.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)) + { + var extension = new JsonApiMediaTypeExtension(extValue); + extensions.Add(extension); + } + } + + public override string ToString() + { + var baseHeaderValue = new MediaTypeHeaderValue(BaseMediaTypeSegment); + List parameters = []; + bool requiresEscape = false; + + foreach (JsonApiMediaTypeExtension extension in Extensions) + { + var extHeaderValue = new NameValueHeaderValue(ExtSegment); + extHeaderValue.SetAndEscapeValue(extension.UnescapedValue); + + if (extHeaderValue.Value != extension.UnescapedValue) + { + requiresEscape = true; + } + + parameters.Add(extHeaderValue); + } + + if (parameters.Count == 1) + { + baseHeaderValue.Parameters.Add(parameters[0]); + } + else if (parameters.Count > 1) + { + if (requiresEscape) + { + // JSON:API requires all 'ext' parameters combined into a single space-separated value. + string compositeValue = string.Join(' ', parameters.Select(parameter => parameter.GetUnescapedValue().ToString())); + var compositeParameter = new NameValueHeaderValue(ExtSegment); + compositeParameter.SetAndEscapeValue(compositeValue); + baseHeaderValue.Parameters.Add(compositeParameter); + } + else + { + // Relaxed mode: use separate 'ext' parameters. + foreach (NameValueHeaderValue parameter in parameters) + { + baseHeaderValue.Parameters.Add(parameter); + } + } + } + + return baseHeaderValue.ToString(); + } + + public bool Equals(JsonApiMediaType? other) + { + if (other is null) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + return Extensions.SetEquals(other.Extensions); + } + + public override bool Equals(object? other) + { + return Equals(other as JsonApiMediaType); + } + + public override int GetHashCode() + { + int hashCode = 0; + + foreach (JsonApiMediaTypeExtension extension in Extensions) + { + hashCode = HashCode.Combine(hashCode, extension); + } + + return hashCode; + } +} diff --git a/src/JsonApiDotNetCore/Middleware/JsonApiMediaTypeExtension.cs b/src/JsonApiDotNetCore/Middleware/JsonApiMediaTypeExtension.cs new file mode 100644 index 0000000000..6ee7ac10ce --- /dev/null +++ b/src/JsonApiDotNetCore/Middleware/JsonApiMediaTypeExtension.cs @@ -0,0 +1,52 @@ +using JetBrains.Annotations; + +namespace JsonApiDotNetCore.Middleware; + +/// +/// Represents a JSON:API extension (in unescaped format), which occurs as an "ext" parameter inside an HTTP Accept or Content-Type header. +/// +[PublicAPI] +public sealed class JsonApiMediaTypeExtension : IEquatable +{ + public static readonly JsonApiMediaTypeExtension AtomicOperations = new("https://jsonapi.org/ext/atomic"); + public static readonly JsonApiMediaTypeExtension RelaxedAtomicOperations = new("atomic"); + + public string UnescapedValue { get; } + + public JsonApiMediaTypeExtension(string unescapedValue) + { + ArgumentException.ThrowIfNullOrEmpty(unescapedValue); + + UnescapedValue = unescapedValue; + } + + public override string ToString() + { + return UnescapedValue; + } + + public bool Equals(JsonApiMediaTypeExtension? other) + { + if (other is null) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + return UnescapedValue == other.UnescapedValue; + } + + public override bool Equals(object? other) + { + return Equals(other as JsonApiMediaTypeExtension); + } + + public override int GetHashCode() + { + return UnescapedValue.GetHashCode(); + } +} diff --git a/src/JsonApiDotNetCore/Middleware/JsonApiMiddleware.cs b/src/JsonApiDotNetCore/Middleware/JsonApiMiddleware.cs index 4d9896ce8a..2084676c8a 100644 --- a/src/JsonApiDotNetCore/Middleware/JsonApiMiddleware.cs +++ b/src/JsonApiDotNetCore/Middleware/JsonApiMiddleware.cs @@ -3,6 +3,7 @@ using JetBrains.Annotations; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Diagnostics; +using JsonApiDotNetCore.Errors; using JsonApiDotNetCore.Resources.Annotations; using JsonApiDotNetCore.Serialization.Objects; using Microsoft.AspNetCore.Http; @@ -18,77 +19,71 @@ namespace JsonApiDotNetCore.Middleware; /// Intercepts HTTP requests to populate injected instance for JSON:API requests. /// [PublicAPI] -public sealed class JsonApiMiddleware +public sealed partial class JsonApiMiddleware { - private static readonly string[] NonOperationsContentTypes = [HeaderConstants.MediaType]; - private static readonly MediaTypeHeaderValue[] NonOperationsMediaTypes = [MediaTypeHeaderValue.Parse(HeaderConstants.MediaType)]; - - private static readonly string[] OperationsContentTypes = - [ - HeaderConstants.AtomicOperationsMediaType, - HeaderConstants.RelaxedAtomicOperationsMediaType - ]; - - private static readonly MediaTypeHeaderValue[] OperationsMediaTypes = - [ - MediaTypeHeaderValue.Parse(HeaderConstants.AtomicOperationsMediaType), - MediaTypeHeaderValue.Parse(HeaderConstants.RelaxedAtomicOperationsMediaType) - ]; - private readonly RequestDelegate? _next; + private readonly IControllerResourceMapping _controllerResourceMapping; + private readonly IJsonApiOptions _options; + private readonly IJsonApiContentNegotiator _contentNegotiator; + private readonly ILogger _logger; - public JsonApiMiddleware(RequestDelegate? next, IHttpContextAccessor httpContextAccessor) + public JsonApiMiddleware(RequestDelegate? next, IHttpContextAccessor httpContextAccessor, IControllerResourceMapping controllerResourceMapping, + IJsonApiOptions options, IJsonApiContentNegotiator contentNegotiator, ILogger logger) { - ArgumentGuard.NotNull(httpContextAccessor); + ArgumentNullException.ThrowIfNull(httpContextAccessor); + ArgumentNullException.ThrowIfNull(controllerResourceMapping); + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(contentNegotiator); + ArgumentNullException.ThrowIfNull(logger); _next = next; + _controllerResourceMapping = controllerResourceMapping; + _options = options; + _contentNegotiator = contentNegotiator; + _logger = logger; +#pragma warning disable CA2000 // Dispose objects before losing scope var session = new AspNetCodeTimerSession(httpContextAccessor); +#pragma warning restore CA2000 // Dispose objects before losing scope CodeTimingSessionManager.Capture(session); } - public async Task InvokeAsync(HttpContext httpContext, IControllerResourceMapping controllerResourceMapping, IJsonApiOptions options, - IJsonApiRequest request, ILogger logger) + public async Task InvokeAsync(HttpContext httpContext, IJsonApiRequest request) { - ArgumentGuard.NotNull(httpContext); - ArgumentGuard.NotNull(controllerResourceMapping); - ArgumentGuard.NotNull(options); - ArgumentGuard.NotNull(request); - ArgumentGuard.NotNull(logger); + ArgumentNullException.ThrowIfNull(httpContext); + ArgumentNullException.ThrowIfNull(request); using (CodeTimingSessionManager.Current.Measure("JSON:API middleware")) { - if (!await ValidateIfMatchHeaderAsync(httpContext, options.SerializerWriteOptions)) - { - return; - } - RouteValueDictionary routeValues = httpContext.GetRouteData().Values; - ResourceType? primaryResourceType = CreatePrimaryResourceType(httpContext, controllerResourceMapping); + ResourceType? primaryResourceType = CreatePrimaryResourceType(httpContext, _controllerResourceMapping); - if (primaryResourceType != null) + bool isResourceRequest = primaryResourceType != null; + bool isOperationsRequest = IsRouteForOperations(routeValues); + + if (isResourceRequest || isOperationsRequest) { - if (!await ValidateContentTypeHeaderAsync(NonOperationsContentTypes, httpContext, options.SerializerWriteOptions) || - !await ValidateAcceptHeaderAsync(NonOperationsMediaTypes, httpContext, options.SerializerWriteOptions)) + try { - return; + ValidateIfMatchHeader(httpContext.Request); + IReadOnlySet extensions = _contentNegotiator.Negotiate(); + + if (isResourceRequest) + { + SetupResourceRequest((JsonApiRequest)request, primaryResourceType!, routeValues, httpContext.Request, extensions); + } + else + { + SetupOperationsRequest((JsonApiRequest)request, extensions); + } + + httpContext.RegisterJsonApiRequest(); } - - SetupResourceRequest((JsonApiRequest)request, primaryResourceType, routeValues, httpContext.Request); - - httpContext.RegisterJsonApiRequest(); - } - else if (IsRouteForOperations(routeValues)) - { - if (!await ValidateContentTypeHeaderAsync(OperationsContentTypes, httpContext, options.SerializerWriteOptions) || - !await ValidateAcceptHeaderAsync(OperationsMediaTypes, httpContext, options.SerializerWriteOptions)) + catch (JsonApiException exception) { + await FlushResponseAsync(httpContext.Response, _options.SerializerWriteOptions, exception); return; } - - SetupOperationsRequest((JsonApiRequest)request); - - httpContext.RegisterJsonApiRequest(); } if (_next != null) @@ -100,20 +95,20 @@ public async Task InvokeAsync(HttpContext httpContext, IControllerResourceMappin } } - if (CodeTimingSessionManager.IsEnabled) + if (CodeTimingSessionManager.IsEnabled && _logger.IsEnabled(LogLevel.Information)) { string timingResults = CodeTimingSessionManager.Current.GetResults(); - string url = httpContext.Request.GetDisplayUrl(); - string method = httpContext.Request.Method.Replace(Environment.NewLine, ""); - logger.LogInformation($"Measurement results for {method} {url}:{Environment.NewLine}{timingResults}"); + string requestMethod = httpContext.Request.Method.Replace(Environment.NewLine, ""); + string requestUrl = httpContext.Request.GetEncodedUrl(); + LogMeasurement(requestMethod, requestUrl, Environment.NewLine, timingResults); } } - private async Task ValidateIfMatchHeaderAsync(HttpContext httpContext, JsonSerializerOptions serializerOptions) + private void ValidateIfMatchHeader(HttpRequest httpRequest) { - if (httpContext.Request.Headers.ContainsKey(HeaderNames.IfMatch)) + if (httpRequest.Headers.ContainsKey(HeaderNames.IfMatch)) { - await FlushResponseAsync(httpContext.Response, serializerOptions, new ErrorObject(HttpStatusCode.PreconditionFailed) + throw new JsonApiException(new ErrorObject(HttpStatusCode.PreconditionFailed) { Title = "Detection of mid-air edit collisions using ETags is not supported.", Source = new ErrorSource @@ -121,11 +116,7 @@ private async Task ValidateIfMatchHeaderAsync(HttpContext httpContext, Jso Header = "If-Match" } }); - - return false; } - - return true; } private static ResourceType? CreatePrimaryResourceType(HttpContext httpContext, IControllerResourceMapping controllerResourceMapping) @@ -138,100 +129,11 @@ private async Task ValidateIfMatchHeaderAsync(HttpContext httpContext, Jso : null; } - private static async Task ValidateContentTypeHeaderAsync(ICollection allowedContentTypes, HttpContext httpContext, - JsonSerializerOptions serializerOptions) - { - string? contentType = httpContext.Request.ContentType; - - if (contentType != null && !allowedContentTypes.Contains(contentType, StringComparer.OrdinalIgnoreCase)) - { - string allowedValues = string.Join(" or ", allowedContentTypes.Select(value => $"'{value}'")); - - await FlushResponseAsync(httpContext.Response, serializerOptions, new ErrorObject(HttpStatusCode.UnsupportedMediaType) - { - Title = "The specified Content-Type header value is not supported.", - Detail = $"Please specify {allowedValues} instead of '{contentType}' for the Content-Type header value.", - Source = new ErrorSource - { - Header = "Content-Type" - } - }); - - return false; - } - - return true; - } - - private static async Task ValidateAcceptHeaderAsync(ICollection allowedMediaTypes, HttpContext httpContext, - JsonSerializerOptions serializerOptions) - { - string[] acceptHeaders = httpContext.Request.Headers.GetCommaSeparatedValues("Accept"); - - if (!acceptHeaders.Any()) - { - return true; - } - - bool seenCompatibleMediaType = false; - - foreach (string acceptHeader in acceptHeaders) - { - if (MediaTypeHeaderValue.TryParse(acceptHeader, out MediaTypeHeaderValue? headerValue)) - { - if (headerValue.MediaType == "*/*" || headerValue.MediaType == "application/*") - { - seenCompatibleMediaType = true; - break; - } - - headerValue.Quality = null; - - if (allowedMediaTypes.Contains(headerValue)) - { - seenCompatibleMediaType = true; - break; - } - } - } - - if (!seenCompatibleMediaType) - { - string allowedValues = string.Join(" or ", allowedMediaTypes.Select(value => $"'{value}'")); - - await FlushResponseAsync(httpContext.Response, serializerOptions, new ErrorObject(HttpStatusCode.NotAcceptable) - { - Title = "The specified Accept header value does not contain any supported media types.", - Detail = $"Please include {allowedValues} in the Accept header values.", - Source = new ErrorSource - { - Header = "Accept" - } - }); - - return false; - } - - return true; - } - - private static async Task FlushResponseAsync(HttpResponse httpResponse, JsonSerializerOptions serializerOptions, ErrorObject error) - { - httpResponse.ContentType = HeaderConstants.MediaType; - httpResponse.StatusCode = (int)error.StatusCode; - - var errorDocument = new Document - { - Errors = [error] - }; - - await JsonSerializer.SerializeAsync(httpResponse.Body, errorDocument, serializerOptions); - await httpResponse.Body.FlushAsync(); - } - private static void SetupResourceRequest(JsonApiRequest request, ResourceType primaryResourceType, RouteValueDictionary routeValues, - HttpRequest httpRequest) + HttpRequest httpRequest, IReadOnlySet extensions) { + AssertNoAtomicOperationsExtension(extensions); + request.IsReadOnly = httpRequest.Method == HttpMethod.Get.Method || httpRequest.Method == HttpMethod.Head.Method; request.PrimaryResourceType = primaryResourceType; request.PrimaryId = GetPrimaryRequestId(routeValues); @@ -279,6 +181,15 @@ private static void SetupResourceRequest(JsonApiRequest request, ResourceType pr bool isGetAll = request.PrimaryId == null && request.IsReadOnly; request.IsCollection = isGetAll || request.Relationship is HasManyAttribute; + request.Extensions = extensions; + } + + private static void AssertNoAtomicOperationsExtension(IReadOnlySet extensions) + { + if (extensions.Contains(JsonApiMediaTypeExtension.AtomicOperations) || extensions.Contains(JsonApiMediaTypeExtension.RelaxedAtomicOperations)) + { + throw new InvalidOperationException("Incorrect content negotiation implementation detected: Unexpected atomic:operations extension found."); + } } private static string? GetPrimaryRequestId(RouteValueDictionary routeValues) @@ -297,15 +208,44 @@ private static bool IsRouteForRelationship(RouteValueDictionary routeValues) return actionName.EndsWith("Relationship", StringComparison.Ordinal); } - private static bool IsRouteForOperations(RouteValueDictionary routeValues) + internal static bool IsRouteForOperations(RouteValueDictionary routeValues) { string actionName = (string)routeValues["action"]!; return actionName == "PostOperations"; } - private static void SetupOperationsRequest(JsonApiRequest request) + private static void SetupOperationsRequest(JsonApiRequest request, IReadOnlySet extensions) { + AssertHasAtomicOperationsExtension(extensions); + request.IsReadOnly = false; request.Kind = EndpointKind.AtomicOperations; + request.Extensions = extensions; + } + + private static void AssertHasAtomicOperationsExtension(IReadOnlySet extensions) + { + if (!extensions.Contains(JsonApiMediaTypeExtension.AtomicOperations) && !extensions.Contains(JsonApiMediaTypeExtension.RelaxedAtomicOperations)) + { + throw new InvalidOperationException("Incorrect content negotiation implementation detected: Missing atomic:operations extension."); + } } + + private static async Task FlushResponseAsync(HttpResponse httpResponse, JsonSerializerOptions serializerOptions, JsonApiException exception) + { + httpResponse.ContentType = JsonApiMediaType.Default.ToString(); + httpResponse.StatusCode = (int)ErrorObject.GetResponseStatusCode(exception.Errors); + + var errorDocument = new Document + { + Errors = exception.Errors.ToList() + }; + + await JsonSerializer.SerializeAsync(httpResponse.Body, errorDocument, serializerOptions); + await httpResponse.Body.FlushAsync(); + } + + [LoggerMessage(Level = LogLevel.Information, SkipEnabledCheck = true, + Message = "Measurement results for {RequestMethod} {RequestUrl}:{LineBreak}{TimingResults}")] + private partial void LogMeasurement(string requestMethod, string requestUrl, string lineBreak, string timingResults); } diff --git a/src/JsonApiDotNetCore/Middleware/JsonApiOutputFormatter.cs b/src/JsonApiDotNetCore/Middleware/JsonApiOutputFormatter.cs index 80d7863251..1f6de39b8b 100644 --- a/src/JsonApiDotNetCore/Middleware/JsonApiOutputFormatter.cs +++ b/src/JsonApiDotNetCore/Middleware/JsonApiOutputFormatter.cs @@ -10,7 +10,7 @@ public sealed class JsonApiOutputFormatter : IJsonApiOutputFormatter /// public bool CanWriteResult(OutputFormatterCanWriteContext context) { - ArgumentGuard.NotNull(context); + ArgumentNullException.ThrowIfNull(context); return context.HttpContext.IsJsonApiRequest(); } @@ -18,7 +18,7 @@ public bool CanWriteResult(OutputFormatterCanWriteContext context) /// public async Task WriteAsync(OutputFormatterWriteContext context) { - ArgumentGuard.NotNull(context); + ArgumentNullException.ThrowIfNull(context); var writer = context.HttpContext.RequestServices.GetRequiredService(); await writer.WriteAsync(context.Object, context.HttpContext); diff --git a/src/JsonApiDotNetCore/Middleware/JsonApiRequest.cs b/src/JsonApiDotNetCore/Middleware/JsonApiRequest.cs index 81e0564311..4f382ec329 100644 --- a/src/JsonApiDotNetCore/Middleware/JsonApiRequest.cs +++ b/src/JsonApiDotNetCore/Middleware/JsonApiRequest.cs @@ -8,6 +8,8 @@ namespace JsonApiDotNetCore.Middleware; [PublicAPI] public sealed class JsonApiRequest : IJsonApiRequest { + private static readonly IReadOnlySet EmptyExtensionSet = new HashSet().AsReadOnly(); + /// public EndpointKind Kind { get; set; } @@ -35,10 +37,13 @@ public sealed class JsonApiRequest : IJsonApiRequest /// public string? TransactionId { get; set; } + /// + public IReadOnlySet Extensions { get; set; } = EmptyExtensionSet; + /// public void CopyFrom(IJsonApiRequest other) { - ArgumentGuard.NotNull(other); + ArgumentNullException.ThrowIfNull(other); Kind = other.Kind; PrimaryId = other.PrimaryId; @@ -49,5 +54,6 @@ public void CopyFrom(IJsonApiRequest other) IsReadOnly = other.IsReadOnly; WriteOperation = other.WriteOperation; TransactionId = other.TransactionId; + Extensions = other.Extensions; } } diff --git a/src/JsonApiDotNetCore/Middleware/JsonApiRoutingConvention.cs b/src/JsonApiDotNetCore/Middleware/JsonApiRoutingConvention.cs index c2df736e96..fd55d4ec5b 100644 --- a/src/JsonApiDotNetCore/Middleware/JsonApiRoutingConvention.cs +++ b/src/JsonApiDotNetCore/Middleware/JsonApiRoutingConvention.cs @@ -7,43 +7,48 @@ using JsonApiDotNetCore.Resources; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ApplicationModels; +using Microsoft.AspNetCore.Mvc.Routing; using Microsoft.Extensions.Logging; namespace JsonApiDotNetCore.Middleware; /// -/// The default routing convention registers the name of the resource as the route using the serializer naming convention. The default for this is a -/// camel case formatter. If the controller directly inherits from and there is no resource directly associated, it -/// uses the name of the controller instead of the name of the type. +/// Registers routes based on the JSON:API resource name, which defaults to camel-case pluralized form of the resource CLR type name. If unavailable (for +/// example, when a controller directly inherits from ), the serializer naming convention is applied on the +/// controller type name (camel-case by default). /// /// { } // => /someResources/relationship/relatedResource +/// // controller name is ignored when resource type is available: +/// public class RandomNameController : JsonApiController { } // => /someResources /// -/// public class RandomNameController : JsonApiController { } // => /someResources/relationship/relatedResource +/// // when using kebab-case naming convention in options: +/// public class RandomNameController : JsonApiController { } // => /some-resources /// -/// // when using kebab-case naming convention: -/// public class SomeResourceController : JsonApiController { } // => /some-resources/relationship/related-resource -/// -/// public class SomeVeryCustomController : CoreJsonApiController { } // => /someVeryCustoms/relationship/relatedResource +/// // unable to determine resource type: +/// public class SomeVeryCustomController : CoreJsonApiController { } // => /someVeryCustom /// ]]> [PublicAPI] -public sealed class JsonApiRoutingConvention : IJsonApiRoutingConvention +public sealed partial class JsonApiRoutingConvention : IJsonApiRoutingConvention { private readonly IJsonApiOptions _options; private readonly IResourceGraph _resourceGraph; + private readonly IJsonApiEndpointFilter _jsonApiEndpointFilter; private readonly ILogger _logger; private readonly Dictionary _registeredControllerNameByTemplate = []; private readonly Dictionary _resourceTypePerControllerTypeMap = []; private readonly Dictionary _controllerPerResourceTypeMap = []; - public JsonApiRoutingConvention(IJsonApiOptions options, IResourceGraph resourceGraph, ILogger logger) + public JsonApiRoutingConvention(IJsonApiOptions options, IResourceGraph resourceGraph, IJsonApiEndpointFilter jsonApiEndpointFilter, + ILogger logger) { - ArgumentGuard.NotNull(options); - ArgumentGuard.NotNull(resourceGraph); - ArgumentGuard.NotNull(logger); + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(resourceGraph); + ArgumentNullException.ThrowIfNull(jsonApiEndpointFilter); + ArgumentNullException.ThrowIfNull(logger); _options = options; _resourceGraph = resourceGraph; + _jsonApiEndpointFilter = jsonApiEndpointFilter; _logger = logger; } @@ -64,7 +69,7 @@ public JsonApiRoutingConvention(IJsonApiOptions options, IResourceGraph resource /// public void Apply(ApplicationModel application) { - ArgumentGuard.NotNull(application); + ArgumentNullException.ThrowIfNull(application); foreach (ControllerModel controller in application.Controllers) { @@ -83,8 +88,7 @@ public void Apply(ApplicationModel application) // ProblemDetails, where the origin of the error gets lost. As a result, we can't populate the source pointer in JSON:API error responses. // For backwards-compatibility, we log a warning instead of throwing. But we can't think of any use cases where having [ApiController] makes sense. - _logger.LogWarning( - $"Found JSON:API controller '{controller.ControllerType}' with [ApiController]. Please remove this attribute for optimal JSON:API compliance."); + LogApiControllerAttributeFound(controller.ControllerType); } if (!IsOperationsController(controller.ControllerType)) @@ -97,8 +101,8 @@ public void Apply(ApplicationModel application) if (resourceType == null) { - throw new InvalidConfigurationException($"Controller '{controller.ControllerType}' depends on " + - $"resource type '{resourceClrType}', which does not exist in the resource graph."); + throw new InvalidConfigurationException( + $"Controller '{controller.ControllerType}' depends on resource type '{resourceClrType}', which does not exist in the resource graph."); } if (_controllerPerResourceTypeMap.TryGetValue(resourceType, out ControllerModel? existingModel)) @@ -107,10 +111,17 @@ public void Apply(ApplicationModel application) $"Multiple controllers found for resource type '{resourceType}': '{existingModel.ControllerType}' and '{controller.ControllerType}'."); } + RemoveDisabledActionMethods(controller, resourceType); + _resourceTypePerControllerTypeMap.Add(controller.ControllerType, resourceType); _controllerPerResourceTypeMap.Add(resourceType, controller); } } + else + { + var options = (JsonApiOptions)_options; + options.IncludeExtensions(JsonApiMediaTypeExtension.AtomicOperations, JsonApiMediaTypeExtension.RelaxedAtomicOperations); + } if (IsRoutingConventionDisabled(controller)) { @@ -144,34 +155,10 @@ private static bool HasApiControllerAttribute(ControllerModel controller) return controller.ControllerType.GetCustomAttribute() != null; } - private static bool IsRoutingConventionDisabled(ControllerModel controller) - { - return controller.ControllerType.GetCustomAttribute(true) != null; - } - - /// - /// Derives a template from the resource type, and checks if this template was already registered. - /// - private string? TemplateFromResource(ControllerModel model) - { - if (_resourceTypePerControllerTypeMap.TryGetValue(model.ControllerType, out ResourceType? resourceType)) - { - return $"{_options.Namespace}/{resourceType.PublicName}"; - } - - return null; - } - - /// - /// Derives a template from the controller name, and checks if this template was already registered. - /// - private string TemplateFromController(ControllerModel model) + private static bool IsOperationsController(Type type) { - string controllerName = _options.SerializerOptions.PropertyNamingPolicy == null - ? model.ControllerName - : _options.SerializerOptions.PropertyNamingPolicy.ConvertName(model.ControllerName); - - return $"{_options.Namespace}/{controllerName}"; + Type baseControllerType = typeof(BaseJsonApiOperationsController); + return baseControllerType.IsAssignableFrom(type); } /// @@ -209,9 +196,50 @@ private string TemplateFromController(ControllerModel model) return currentType?.GetGenericArguments().First(); } - private static bool IsOperationsController(Type type) + private void RemoveDisabledActionMethods(ControllerModel controller, ResourceType resourceType) { - Type baseControllerType = typeof(BaseJsonApiOperationsController); - return baseControllerType.IsAssignableFrom(type); + foreach (ActionModel actionModel in controller.Actions.ToArray()) + { + JsonApiEndpoints endpoint = actionModel.Attributes.OfType().GetJsonApiEndpoint(); + + if (endpoint != JsonApiEndpoints.None && !_jsonApiEndpointFilter.IsEnabled(resourceType, endpoint)) + { + controller.Actions.Remove(actionModel); + } + } } + + private static bool IsRoutingConventionDisabled(ControllerModel controller) + { + return controller.ControllerType.GetCustomAttribute(true) != null; + } + + /// + /// Derives a template from the resource type, and checks if this template was already registered. + /// + private string? TemplateFromResource(ControllerModel model) + { + if (_resourceTypePerControllerTypeMap.TryGetValue(model.ControllerType, out ResourceType? resourceType)) + { + return $"{_options.Namespace}/{resourceType.PublicName}"; + } + + return null; + } + + /// + /// Derives a template from the controller name, and checks if this template was already registered. + /// + private string TemplateFromController(ControllerModel model) + { + string controllerName = _options.SerializerOptions.PropertyNamingPolicy == null + ? model.ControllerName + : _options.SerializerOptions.PropertyNamingPolicy.ConvertName(model.ControllerName); + + return $"{_options.Namespace}/{controllerName}"; + } + + [LoggerMessage(Level = LogLevel.Warning, + Message = "Found JSON:API controller '{ControllerType}' with [ApiController]. Please remove this attribute for optimal JSON:API compliance.")] + private partial void LogApiControllerAttributeFound(TypeInfo controllerType); } diff --git a/src/JsonApiDotNetCore/Middleware/TraceLogWriter.cs b/src/JsonApiDotNetCore/Middleware/TraceLogWriter.cs index e17f02ed21..70ed7fdd01 100644 --- a/src/JsonApiDotNetCore/Middleware/TraceLogWriter.cs +++ b/src/JsonApiDotNetCore/Middleware/TraceLogWriter.cs @@ -118,43 +118,29 @@ public override void Write(Utf8JsonWriter writer, TWrapper value, JsonSerializer } } -internal sealed class TraceLogWriter(ILoggerFactory loggerFactory) : TraceLogWriter +internal sealed partial class TraceLogWriter(ILoggerFactory loggerFactory) : TraceLogWriter { - private readonly ILogger _logger = loggerFactory.CreateLogger(typeof(T)); - - private bool IsEnabled => _logger.IsEnabled(LogLevel.Trace); + private readonly ILogger _logger = loggerFactory.CreateLogger(); public void LogMethodStart(object? parameters = null, [CallerMemberName] string memberName = "") { - if (IsEnabled) + if (_logger.IsEnabled(LogLevel.Trace)) { - string message = FormatMessage(memberName, parameters); - WriteMessageToLog(message); - } - } + var builder = new StringBuilder(); + WriteProperties(builder, parameters); + string parameterValues = builder.ToString(); - public void LogMessage(Func messageFactory) - { - if (IsEnabled) - { - string message = messageFactory(); - WriteMessageToLog(message); + if (parameterValues.Length == 0) + { + LogEnteringMember(memberName); + } + else + { + LogEnteringMemberWithParameters(memberName, parameterValues); + } } } - private static string FormatMessage(string memberName, object? parameters) - { - var builder = new StringBuilder(); - - builder.Append("Entering "); - builder.Append(memberName); - builder.Append('('); - WriteProperties(builder, parameters); - builder.Append(')'); - - return builder.ToString(); - } - private static void WriteProperties(StringBuilder builder, object? propertyContainer) { if (propertyContainer != null) @@ -218,8 +204,9 @@ private static string SerializeObject(object? value) } } - private void WriteMessageToLog(string message) - { - _logger.LogTrace(message); - } + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, Message = "Entering {MemberName}({ParameterValues})")] + private partial void LogEnteringMemberWithParameters(string memberName, string parameterValues); + + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, Message = "Entering {MemberName}()")] + private partial void LogEnteringMember(string memberName); } diff --git a/src/JsonApiDotNetCore/Properties/AssemblyInfo.cs b/src/JsonApiDotNetCore/Properties/AssemblyInfo.cs index b8d6038508..051885a6bc 100644 --- a/src/JsonApiDotNetCore/Properties/AssemblyInfo.cs +++ b/src/JsonApiDotNetCore/Properties/AssemblyInfo.cs @@ -2,5 +2,6 @@ [assembly: InternalsVisibleTo("Benchmarks")] [assembly: InternalsVisibleTo("DapperExample")] +[assembly: InternalsVisibleTo("JsonApiDotNetCore.OpenApi.Swashbuckle")] [assembly: InternalsVisibleTo("JsonApiDotNetCoreTests")] [assembly: InternalsVisibleTo("UnitTests")] diff --git a/src/JsonApiDotNetCore/Queries/EvaluatedIncludeCache.cs b/src/JsonApiDotNetCore/Queries/EvaluatedIncludeCache.cs index 7c9d983d63..72a311d246 100644 --- a/src/JsonApiDotNetCore/Queries/EvaluatedIncludeCache.cs +++ b/src/JsonApiDotNetCore/Queries/EvaluatedIncludeCache.cs @@ -5,21 +5,21 @@ namespace JsonApiDotNetCore.Queries; /// internal sealed class EvaluatedIncludeCache : IEvaluatedIncludeCache { - private readonly IEnumerable _constraintProviders; + private readonly IQueryConstraintProvider[] _constraintProviders; private IncludeExpression? _include; private bool _isAssigned; public EvaluatedIncludeCache(IEnumerable constraintProviders) { - ArgumentGuard.NotNull(constraintProviders); + ArgumentNullException.ThrowIfNull(constraintProviders); - _constraintProviders = constraintProviders; + _constraintProviders = constraintProviders as IQueryConstraintProvider[] ?? constraintProviders.ToArray(); } /// public void Set(IncludeExpression include) { - ArgumentGuard.NotNull(include); + ArgumentNullException.ThrowIfNull(include); _include = include; _isAssigned = true; diff --git a/src/JsonApiDotNetCore/Queries/ExpressionInScope.cs b/src/JsonApiDotNetCore/Queries/ExpressionInScope.cs index 6ac6f75059..4cab3e203b 100644 --- a/src/JsonApiDotNetCore/Queries/ExpressionInScope.cs +++ b/src/JsonApiDotNetCore/Queries/ExpressionInScope.cs @@ -15,7 +15,7 @@ public class ExpressionInScope public ExpressionInScope(ResourceFieldChainExpression? scope, QueryExpression expression) { - ArgumentGuard.NotNull(expression); + ArgumentNullException.ThrowIfNull(expression); Scope = scope; Expression = expression; diff --git a/src/JsonApiDotNetCore/Queries/Expressions/AnyExpression.cs b/src/JsonApiDotNetCore/Queries/Expressions/AnyExpression.cs index dfa7536b03..306a98d1aa 100644 --- a/src/JsonApiDotNetCore/Queries/Expressions/AnyExpression.cs +++ b/src/JsonApiDotNetCore/Queries/Expressions/AnyExpression.cs @@ -28,7 +28,7 @@ public class AnyExpression : FilterExpression public AnyExpression(ResourceFieldChainExpression targetAttribute, IImmutableSet constants) { - ArgumentGuard.NotNull(targetAttribute); + ArgumentNullException.ThrowIfNull(targetAttribute); ArgumentGuard.NotNullNorEmpty(constants); TargetAttribute = targetAttribute; diff --git a/src/JsonApiDotNetCore/Queries/Expressions/ComparisonExpression.cs b/src/JsonApiDotNetCore/Queries/Expressions/ComparisonExpression.cs index 9259560776..b768f556ce 100644 --- a/src/JsonApiDotNetCore/Queries/Expressions/ComparisonExpression.cs +++ b/src/JsonApiDotNetCore/Queries/Expressions/ComparisonExpression.cs @@ -40,8 +40,8 @@ public class ComparisonExpression : FilterExpression public ComparisonExpression(ComparisonOperator @operator, QueryExpression left, QueryExpression right) { - ArgumentGuard.NotNull(left); - ArgumentGuard.NotNull(right); + ArgumentNullException.ThrowIfNull(left); + ArgumentNullException.ThrowIfNull(right); Operator = @operator; Left = left; diff --git a/src/JsonApiDotNetCore/Queries/Expressions/CountExpression.cs b/src/JsonApiDotNetCore/Queries/Expressions/CountExpression.cs index 960cf6371b..f79c49af1b 100644 --- a/src/JsonApiDotNetCore/Queries/Expressions/CountExpression.cs +++ b/src/JsonApiDotNetCore/Queries/Expressions/CountExpression.cs @@ -26,7 +26,7 @@ public class CountExpression : FunctionExpression public CountExpression(ResourceFieldChainExpression targetCollection) { - ArgumentGuard.NotNull(targetCollection); + ArgumentNullException.ThrowIfNull(targetCollection); TargetCollection = targetCollection; } diff --git a/src/JsonApiDotNetCore/Queries/Expressions/HasExpression.cs b/src/JsonApiDotNetCore/Queries/Expressions/HasExpression.cs index 709fd60916..5c40039d4e 100644 --- a/src/JsonApiDotNetCore/Queries/Expressions/HasExpression.cs +++ b/src/JsonApiDotNetCore/Queries/Expressions/HasExpression.cs @@ -32,7 +32,7 @@ public class HasExpression : FilterExpression public HasExpression(ResourceFieldChainExpression targetCollection, FilterExpression? filter) { - ArgumentGuard.NotNull(targetCollection); + ArgumentNullException.ThrowIfNull(targetCollection); TargetCollection = targetCollection; Filter = filter; diff --git a/src/JsonApiDotNetCore/Queries/Expressions/IncludeChainConverter.cs b/src/JsonApiDotNetCore/Queries/Expressions/IncludeChainConverter.cs index f88cb60a86..c729c692b9 100644 --- a/src/JsonApiDotNetCore/Queries/Expressions/IncludeChainConverter.cs +++ b/src/JsonApiDotNetCore/Queries/Expressions/IncludeChainConverter.cs @@ -29,9 +29,9 @@ internal sealed class IncludeChainConverter /// public IReadOnlyCollection GetRelationshipChains(IncludeExpression include) { - ArgumentGuard.NotNull(include); + ArgumentNullException.ThrowIfNull(include); - if (!include.Elements.Any()) + if (include.Elements.Count == 0) { return Array.Empty(); } @@ -39,7 +39,7 @@ public IReadOnlyCollection GetRelationshipChains(I var converter = new IncludeToChainsConverter(); converter.Visit(include, null); - return converter.Chains; + return converter.Chains.AsReadOnly(); } private sealed class IncludeToChainsConverter : QueryExpressionVisitor @@ -60,7 +60,7 @@ private sealed class IncludeToChainsConverter : QueryExpressionVisitor children) { - ArgumentGuard.NotNull(relationship); - ArgumentGuard.NotNull(children); + ArgumentNullException.ThrowIfNull(relationship); + ArgumentNullException.ThrowIfNull(children); Relationship = relationship; Children = children; @@ -59,7 +59,7 @@ private string InnerToString(bool toFullString) var builder = new StringBuilder(); builder.Append(toFullString ? $"{Relationship.LeftType.PublicName}:{Relationship.PublicName}" : Relationship.PublicName); - if (Children.Any()) + if (Children.Count > 0) { builder.Append('{'); builder.Append(string.Join(",", Children.Select(child => toFullString ? child.ToFullString() : child.ToString()).OrderBy(name => name))); diff --git a/src/JsonApiDotNetCore/Queries/Expressions/IsTypeExpression.cs b/src/JsonApiDotNetCore/Queries/Expressions/IsTypeExpression.cs index c916aff3bc..e2f68ee8ec 100644 --- a/src/JsonApiDotNetCore/Queries/Expressions/IsTypeExpression.cs +++ b/src/JsonApiDotNetCore/Queries/Expressions/IsTypeExpression.cs @@ -41,7 +41,7 @@ public class IsTypeExpression : FilterExpression public IsTypeExpression(ResourceFieldChainExpression? targetToOneRelationship, ResourceType derivedType, FilterExpression? child) { - ArgumentGuard.NotNull(derivedType); + ArgumentNullException.ThrowIfNull(derivedType); TargetToOneRelationship = targetToOneRelationship; DerivedType = derivedType; diff --git a/src/JsonApiDotNetCore/Queries/Expressions/LiteralConstantExpression.cs b/src/JsonApiDotNetCore/Queries/Expressions/LiteralConstantExpression.cs index 1592aadcfd..50c3b2cd54 100644 --- a/src/JsonApiDotNetCore/Queries/Expressions/LiteralConstantExpression.cs +++ b/src/JsonApiDotNetCore/Queries/Expressions/LiteralConstantExpression.cs @@ -24,8 +24,8 @@ public LiteralConstantExpression(object typedValue) public LiteralConstantExpression(object typedValue, string stringValue) { - ArgumentGuard.NotNull(typedValue); - ArgumentGuard.NotNull(stringValue); + ArgumentNullException.ThrowIfNull(typedValue); + ArgumentNullException.ThrowIfNull(stringValue); TypedValue = typedValue; _stringValue = stringValue; @@ -33,7 +33,7 @@ public LiteralConstantExpression(object typedValue, string stringValue) private static string? GetStringValue(object typedValue) { - ArgumentGuard.NotNull(typedValue); + ArgumentNullException.ThrowIfNull(typedValue); return typedValue is IFormattable cultureAwareValue ? cultureAwareValue.ToString(null, CultureInfo.InvariantCulture) : typedValue.ToString(); } diff --git a/src/JsonApiDotNetCore/Queries/Expressions/LogicalExpression.cs b/src/JsonApiDotNetCore/Queries/Expressions/LogicalExpression.cs index f1a9ba8c1c..416303b06b 100644 --- a/src/JsonApiDotNetCore/Queries/Expressions/LogicalExpression.cs +++ b/src/JsonApiDotNetCore/Queries/Expressions/LogicalExpression.cs @@ -37,7 +37,7 @@ public LogicalExpression(LogicalOperator @operator, params FilterExpression[] te public LogicalExpression(LogicalOperator @operator, IImmutableList terms) { - ArgumentGuard.NotNull(terms); + ArgumentNullException.ThrowIfNull(terms); if (terms.Count < 2) { @@ -50,7 +50,7 @@ public LogicalExpression(LogicalOperator @operator, IImmutableList(QueryExpressionVisitor visitor, TArgument argument) { - return visitor.PaginationElementQueryStringValue(this, argument); + return visitor.VisitPaginationElementQueryStringValue(this, argument); } public override string ToString() diff --git a/src/JsonApiDotNetCore/Queries/Expressions/PaginationExpression.cs b/src/JsonApiDotNetCore/Queries/Expressions/PaginationExpression.cs index af20bc3f61..d9e91ef363 100644 --- a/src/JsonApiDotNetCore/Queries/Expressions/PaginationExpression.cs +++ b/src/JsonApiDotNetCore/Queries/Expressions/PaginationExpression.cs @@ -21,7 +21,7 @@ public class PaginationExpression : QueryExpression public PaginationExpression(PageNumber pageNumber, PageSize? pageSize) { - ArgumentGuard.NotNull(pageNumber); + ArgumentNullException.ThrowIfNull(pageNumber); PageNumber = pageNumber; PageSize = pageSize; diff --git a/src/JsonApiDotNetCore/Queries/Expressions/PaginationQueryStringValueExpression.cs b/src/JsonApiDotNetCore/Queries/Expressions/PaginationQueryStringValueExpression.cs index f16ca0cbd6..2a70ea7d8c 100644 --- a/src/JsonApiDotNetCore/Queries/Expressions/PaginationQueryStringValueExpression.cs +++ b/src/JsonApiDotNetCore/Queries/Expressions/PaginationQueryStringValueExpression.cs @@ -27,7 +27,7 @@ public PaginationQueryStringValueExpression(IImmutableList(QueryExpressionVisitor visitor, TArgument argument) { - return visitor.PaginationQueryStringValue(this, argument); + return visitor.VisitPaginationQueryStringValue(this, argument); } public override string ToString() diff --git a/src/JsonApiDotNetCore/Queries/Expressions/QueryExpressionRewriter.cs b/src/JsonApiDotNetCore/Queries/Expressions/QueryExpressionRewriter.cs index 4439e37c21..173c77503c 100644 --- a/src/JsonApiDotNetCore/Queries/Expressions/QueryExpressionRewriter.cs +++ b/src/JsonApiDotNetCore/Queries/Expressions/QueryExpressionRewriter.cs @@ -2,6 +2,8 @@ using JetBrains.Annotations; using JsonApiDotNetCore.Configuration; +#pragma warning disable IDE0019 // Use pattern matching + namespace JsonApiDotNetCore.Queries.Expressions; /// @@ -214,7 +216,7 @@ public override QueryExpression VisitSparseFieldSet(SparseFieldSetExpression exp return null; } - public override QueryExpression PaginationQueryStringValue(PaginationQueryStringValueExpression expression, TArgument argument) + public override QueryExpression VisitPaginationQueryStringValue(PaginationQueryStringValueExpression expression, TArgument argument) { IImmutableList newElements = VisitList(expression.Elements, argument); @@ -222,7 +224,7 @@ public override QueryExpression PaginationQueryStringValue(PaginationQueryString return newExpression.Equals(expression) ? expression : newExpression; } - public override QueryExpression PaginationElementQueryStringValue(PaginationElementQueryStringValueExpression expression, TArgument argument) + public override QueryExpression VisitPaginationElementQueryStringValue(PaginationElementQueryStringValueExpression expression, TArgument argument) { ResourceFieldChainExpression? newScope = expression.Scope != null ? Visit(expression.Scope, argument) as ResourceFieldChainExpression : null; diff --git a/src/JsonApiDotNetCore/Queries/Expressions/QueryExpressionVisitor.cs b/src/JsonApiDotNetCore/Queries/Expressions/QueryExpressionVisitor.cs index 12242c29ff..a0472306f7 100644 --- a/src/JsonApiDotNetCore/Queries/Expressions/QueryExpressionVisitor.cs +++ b/src/JsonApiDotNetCore/Queries/Expressions/QueryExpressionVisitor.cs @@ -109,12 +109,12 @@ public virtual TResult VisitQueryStringParameterScope(QueryStringParameterScopeE return DefaultVisit(expression, argument); } - public virtual TResult PaginationQueryStringValue(PaginationQueryStringValueExpression expression, TArgument argument) + public virtual TResult VisitPaginationQueryStringValue(PaginationQueryStringValueExpression expression, TArgument argument) { return DefaultVisit(expression, argument); } - public virtual TResult PaginationElementQueryStringValue(PaginationElementQueryStringValueExpression expression, TArgument argument) + public virtual TResult VisitPaginationElementQueryStringValue(PaginationElementQueryStringValueExpression expression, TArgument argument) { return DefaultVisit(expression, argument); } diff --git a/src/JsonApiDotNetCore/Queries/Expressions/QueryStringParameterScopeExpression.cs b/src/JsonApiDotNetCore/Queries/Expressions/QueryStringParameterScopeExpression.cs index 9bc17fd3fa..4063199dd2 100644 --- a/src/JsonApiDotNetCore/Queries/Expressions/QueryStringParameterScopeExpression.cs +++ b/src/JsonApiDotNetCore/Queries/Expressions/QueryStringParameterScopeExpression.cs @@ -29,7 +29,7 @@ public class QueryStringParameterScopeExpression : QueryExpression public QueryStringParameterScopeExpression(LiteralConstantExpression parameterName, ResourceFieldChainExpression? scope) { - ArgumentGuard.NotNull(parameterName); + ArgumentNullException.ThrowIfNull(parameterName); ParameterName = parameterName; Scope = scope; diff --git a/src/JsonApiDotNetCore/Queries/Expressions/QueryableHandlerExpression.cs b/src/JsonApiDotNetCore/Queries/Expressions/QueryableHandlerExpression.cs index 872cdb1aac..e3894e7e1f 100644 --- a/src/JsonApiDotNetCore/Queries/Expressions/QueryableHandlerExpression.cs +++ b/src/JsonApiDotNetCore/Queries/Expressions/QueryableHandlerExpression.cs @@ -15,7 +15,7 @@ public class QueryableHandlerExpression : QueryExpression public QueryableHandlerExpression(object queryableHandler, StringValues parameterValue) { - ArgumentGuard.NotNull(queryableHandler); + ArgumentNullException.ThrowIfNull(queryableHandler); _queryableHandler = queryableHandler; _parameterValue = parameterValue; diff --git a/src/JsonApiDotNetCore/Queries/Expressions/ResourceFieldChainExpression.cs b/src/JsonApiDotNetCore/Queries/Expressions/ResourceFieldChainExpression.cs index 993e11f4f4..35d5ecc4a1 100644 --- a/src/JsonApiDotNetCore/Queries/Expressions/ResourceFieldChainExpression.cs +++ b/src/JsonApiDotNetCore/Queries/Expressions/ResourceFieldChainExpression.cs @@ -26,7 +26,7 @@ public class ResourceFieldChainExpression : IdentifierExpression public ResourceFieldChainExpression(ResourceFieldAttribute field) { - ArgumentGuard.NotNull(field); + ArgumentNullException.ThrowIfNull(field); Fields = ImmutableArray.Create(field); } diff --git a/src/JsonApiDotNetCore/Queries/Expressions/SortElementExpression.cs b/src/JsonApiDotNetCore/Queries/Expressions/SortElementExpression.cs index 154c44d159..293c1d9c71 100644 --- a/src/JsonApiDotNetCore/Queries/Expressions/SortElementExpression.cs +++ b/src/JsonApiDotNetCore/Queries/Expressions/SortElementExpression.cs @@ -29,7 +29,7 @@ public class SortElementExpression : QueryExpression public SortElementExpression(QueryExpression target, bool isAscending) { - ArgumentGuard.NotNull(target); + ArgumentNullException.ThrowIfNull(target); Target = target; IsAscending = isAscending; diff --git a/src/JsonApiDotNetCore/Queries/Expressions/SparseFieldSetExpressionExtensions.cs b/src/JsonApiDotNetCore/Queries/Expressions/SparseFieldSetExpressionExtensions.cs index c7c331eb46..936071ffd1 100644 --- a/src/JsonApiDotNetCore/Queries/Expressions/SparseFieldSetExpressionExtensions.cs +++ b/src/JsonApiDotNetCore/Queries/Expressions/SparseFieldSetExpressionExtensions.cs @@ -14,8 +14,8 @@ public static class SparseFieldSetExpressionExtensions Expression> fieldSelector, IResourceGraph resourceGraph) where TResource : class, IIdentifiable { - ArgumentGuard.NotNull(fieldSelector); - ArgumentGuard.NotNull(resourceGraph); + ArgumentNullException.ThrowIfNull(fieldSelector); + ArgumentNullException.ThrowIfNull(resourceGraph); SparseFieldSetExpression? newSparseFieldSet = sparseFieldSet; @@ -42,8 +42,8 @@ public static class SparseFieldSetExpressionExtensions Expression> fieldSelector, IResourceGraph resourceGraph) where TResource : class, IIdentifiable { - ArgumentGuard.NotNull(fieldSelector); - ArgumentGuard.NotNull(resourceGraph); + ArgumentNullException.ThrowIfNull(fieldSelector); + ArgumentNullException.ThrowIfNull(resourceGraph); SparseFieldSetExpression? newSparseFieldSet = sparseFieldSet; diff --git a/src/JsonApiDotNetCore/Queries/FieldSelection.cs b/src/JsonApiDotNetCore/Queries/FieldSelection.cs index 7f62db1fcf..b929db2c80 100644 --- a/src/JsonApiDotNetCore/Queries/FieldSelection.cs +++ b/src/JsonApiDotNetCore/Queries/FieldSelection.cs @@ -16,14 +16,14 @@ public sealed class FieldSelection : Dictionary public IReadOnlySet GetResourceTypes() { - return Keys.ToHashSet(); + return Keys.ToHashSet().AsReadOnly(); } #pragma warning disable AV1130 // Return type in method signature should be an interface to an unchangeable collection public FieldSelectors GetOrCreateSelectors(ResourceType resourceType) #pragma warning restore AV1130 // Return type in method signature should be an interface to an unchangeable collection { - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(resourceType); if (!ContainsKey(resourceType)) { diff --git a/src/JsonApiDotNetCore/Queries/FieldSelectors.cs b/src/JsonApiDotNetCore/Queries/FieldSelectors.cs index 63415cfffc..d9ab815638 100644 --- a/src/JsonApiDotNetCore/Queries/FieldSelectors.cs +++ b/src/JsonApiDotNetCore/Queries/FieldSelectors.cs @@ -30,21 +30,21 @@ public bool ContainsOnlyRelationships public bool ContainsField(ResourceFieldAttribute field) { - ArgumentGuard.NotNull(field); + ArgumentNullException.ThrowIfNull(field); return ContainsKey(field); } public void IncludeAttribute(AttrAttribute attribute) { - ArgumentGuard.NotNull(attribute); + ArgumentNullException.ThrowIfNull(attribute); this[attribute] = null; } public void IncludeAttributes(IEnumerable attributes) { - ArgumentGuard.NotNull(attributes); + ArgumentNullException.ThrowIfNull(attributes); foreach (AttrAttribute attribute in attributes) { @@ -54,8 +54,8 @@ public void IncludeAttributes(IEnumerable attributes) public void IncludeRelationship(RelationshipAttribute relationship, QueryLayer queryLayer) { - ArgumentGuard.NotNull(relationship); - ArgumentGuard.NotNull(queryLayer); + ArgumentNullException.ThrowIfNull(relationship); + ArgumentNullException.ThrowIfNull(queryLayer); this[relationship] = queryLayer; } diff --git a/src/JsonApiDotNetCore/Queries/Parsing/FilterParser.cs b/src/JsonApiDotNetCore/Queries/Parsing/FilterParser.cs index 077d727368..f89bf3dc39 100644 --- a/src/JsonApiDotNetCore/Queries/Parsing/FilterParser.cs +++ b/src/JsonApiDotNetCore/Queries/Parsing/FilterParser.cs @@ -54,7 +54,7 @@ protected ResourceType ResourceTypeInScope public FilterParser(IResourceFactory resourceFactory) { - ArgumentGuard.NotNull(resourceFactory); + ArgumentNullException.ThrowIfNull(resourceFactory); _resourceFactory = resourceFactory; } @@ -62,7 +62,7 @@ public FilterParser(IResourceFactory resourceFactory) /// public FilterExpression Parse(string source, ResourceType resourceType) { - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(resourceType); Tokenize(source); @@ -83,7 +83,7 @@ public FilterExpression Parse(string source, ResourceType resourceType) protected virtual bool IsFunction(string name) { - ArgumentGuard.NotNullNorEmpty(name); + ArgumentException.ThrowIfNullOrEmpty(name); return name == Keywords.Count || FilterKeywords.Contains(name); } @@ -179,6 +179,8 @@ protected virtual NotExpression ParseNot() protected virtual LogicalExpression ParseLogical(string operatorName) { + ArgumentException.ThrowIfNullOrEmpty(operatorName); + EatText(operatorName); EatSingleCharacterToken(TokenKind.OpenParen); @@ -208,6 +210,8 @@ protected virtual LogicalExpression ParseLogical(string operatorName) protected virtual ComparisonExpression ParseComparison(string operatorName) { + ArgumentException.ThrowIfNullOrEmpty(operatorName); + var comparisonOperator = Enum.Parse(operatorName.Pascalize()); EatText(operatorName); @@ -311,6 +315,8 @@ private QueryExpression ParseTypedComparisonRightTerm(Type leftType, ConstantVal protected virtual MatchTextExpression ParseTextMatch(string operatorName) { + ArgumentException.ThrowIfNullOrEmpty(operatorName); + EatText(operatorName); EatSingleCharacterToken(TokenKind.OpenParen); @@ -516,6 +522,8 @@ private NullConstantExpression ParseNull() protected virtual ConstantValueConverter GetConstantValueConverterForType(Type destinationType) { + ArgumentNullException.ThrowIfNull(destinationType); + return (stringValue, position) => { try @@ -558,6 +566,8 @@ private object DeObfuscateStringId(ResourceType resourceType, string stringId) protected override void ValidateField(ResourceFieldAttribute field, int position) { + ArgumentNullException.ThrowIfNull(field); + if (field.IsFilterBlocked()) { string kind = field is AttrAttribute ? "attribute" : "relationship"; @@ -570,7 +580,7 @@ protected override void ValidateField(ResourceFieldAttribute field, int position /// protected IDisposable InScopeOfResourceType(ResourceType resourceType) { - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(resourceType); _resourceTypeStack.Push(resourceType); return new PopResourceTypeOnDispose(_resourceTypeStack); diff --git a/src/JsonApiDotNetCore/Queries/Parsing/IncludeParser.cs b/src/JsonApiDotNetCore/Queries/Parsing/IncludeParser.cs index 1ab0e61326..eb328f3183 100644 --- a/src/JsonApiDotNetCore/Queries/Parsing/IncludeParser.cs +++ b/src/JsonApiDotNetCore/Queries/Parsing/IncludeParser.cs @@ -1,4 +1,5 @@ using System.Collections.Immutable; +using System.Collections.ObjectModel; using System.Text; using JetBrains.Annotations; using JsonApiDotNetCore.Configuration; @@ -16,7 +17,7 @@ public class IncludeParser : QueryExpressionParser, IIncludeParser public IncludeParser(IJsonApiOptions options) { - ArgumentGuard.NotNull(options); + ArgumentNullException.ThrowIfNull(options); _options = options; } @@ -24,7 +25,7 @@ public IncludeParser(IJsonApiOptions options) /// public IncludeExpression Parse(string source, ResourceType resourceType) { - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(resourceType); Tokenize(source); @@ -38,10 +39,13 @@ public IncludeExpression Parse(string source, ResourceType resourceType) protected virtual IncludeExpression ParseInclude(string source, ResourceType resourceType) { + ArgumentNullException.ThrowIfNull(source); + ArgumentNullException.ThrowIfNull(resourceType); + var treeRoot = IncludeTreeNode.CreateRoot(resourceType); bool isAtStart = true; - while (TokenStack.Any()) + while (TokenStack.Count > 0) { if (!isAtStart) { @@ -86,7 +90,7 @@ private void ParseRelationshipChain(string source, IncludeTreeNode treeRoot) // that there's currently no way to include Products without Articles. We could add such optional upcast syntax // in the future, if desired. - ICollection children = ParseRelationshipName(source, [treeRoot]); + ReadOnlyCollection children = ParseRelationshipName(source, [treeRoot]); while (TokenStack.TryPeek(out Token? nextToken) && nextToken.Kind == TokenKind.Period) { @@ -96,7 +100,7 @@ private void ParseRelationshipChain(string source, IncludeTreeNode treeRoot) } } - private ICollection ParseRelationshipName(string source, ICollection parents) + private ReadOnlyCollection ParseRelationshipName(string source, IReadOnlyCollection parents) { int position = GetNextTokenPositionOrEnd(); @@ -108,8 +112,8 @@ private ICollection ParseRelationshipName(string source, IColle throw new QueryParseException("Relationship name expected.", position); } - private static ICollection LookupRelationshipName(string relationshipName, ICollection parents, string source, - int position) + private static ReadOnlyCollection LookupRelationshipName(string relationshipName, IReadOnlyCollection parents, + string source, int position) { List children = []; HashSet relationshipsFound = []; @@ -118,14 +122,14 @@ private static ICollection LookupRelationshipName(string relati { // Depending on the left side of the include chain, we may match relationships anywhere in the resource type hierarchy. // This is compensated for when rendering the response, which substitutes relationships on base types with the derived ones. - IReadOnlySet relationships = parent.Relationship.RightType.GetRelationshipsInTypeOrDerived(relationshipName); + HashSet relationships = GetRelationshipsInConcreteTypes(parent.Relationship.RightType, relationshipName); - if (relationships.Any()) + if (relationships.Count > 0) { relationshipsFound.UnionWith(relationships); RelationshipAttribute[] relationshipsToInclude = relationships.Where(relationship => !relationship.IsIncludeBlocked()).ToArray(); - ICollection affectedChildren = parent.EnsureChildren(relationshipsToInclude); + ReadOnlyCollection affectedChildren = parent.EnsureChildren(relationshipsToInclude); children.AddRange(affectedChildren); } } @@ -133,13 +137,39 @@ private static ICollection LookupRelationshipName(string relati AssertRelationshipsFound(relationshipsFound, relationshipName, parents, position); AssertAtLeastOneCanBeIncluded(relationshipsFound, relationshipName, source, position); - return children; + return children.AsReadOnly(); } - private static void AssertRelationshipsFound(ISet relationshipsFound, string relationshipName, ICollection parents, - int position) + private static HashSet GetRelationshipsInConcreteTypes(ResourceType resourceType, string relationshipName) + { + HashSet relationshipsToInclude = []; + + foreach (RelationshipAttribute relationship in resourceType.GetRelationshipsInTypeOrDerived(relationshipName)) + { + if (!relationship.LeftType.ClrType.IsAbstract) + { + relationshipsToInclude.Add(relationship); + } + + IncludeRelationshipsFromConcreteDerivedTypes(relationship, relationshipsToInclude); + } + + return relationshipsToInclude; + } + + private static void IncludeRelationshipsFromConcreteDerivedTypes(RelationshipAttribute relationship, HashSet relationshipsToInclude) + { + foreach (ResourceType derivedType in relationship.LeftType.GetAllConcreteDerivedTypes()) + { + RelationshipAttribute relationshipInDerived = derivedType.GetRelationshipByPublicName(relationship.PublicName); + relationshipsToInclude.Add(relationshipInDerived); + } + } + + private static void AssertRelationshipsFound(HashSet relationshipsFound, string relationshipName, + IReadOnlyCollection parents, int position) { - if (relationshipsFound.Any()) + if (relationshipsFound.Count > 0) { return; } @@ -152,11 +182,11 @@ private static void AssertRelationshipsFound(ISet relatio throw new QueryParseException(message, position); } - private static string GetErrorMessageForNoneFound(string relationshipName, ICollection parentResourceTypes, bool hasDerivedTypes) + private static string GetErrorMessageForNoneFound(string relationshipName, ResourceType[] parentResourceTypes, bool hasDerivedTypes) { var builder = new StringBuilder($"Relationship '{relationshipName}'"); - if (parentResourceTypes.Count == 1) + if (parentResourceTypes.Length == 1) { builder.Append($" does not exist on resource type '{parentResourceTypes.First().PublicName}'"); } @@ -171,7 +201,7 @@ private static string GetErrorMessageForNoneFound(string relationshipName, IColl return builder.ToString(); } - private static void AssertAtLeastOneCanBeIncluded(ISet relationshipsFound, string relationshipName, string source, int position) + private static void AssertAtLeastOneCanBeIncluded(HashSet relationshipsFound, string relationshipName, string source, int position) { if (relationshipsFound.All(relationship => relationship.IsIncludeBlocked())) { @@ -220,7 +250,7 @@ private static void ThrowIfMaximumDepthExceeded(IncludeElementExpression include private sealed class IncludeTreeNode { - private readonly IDictionary _children = new Dictionary(); + private readonly Dictionary _children = []; public RelationshipAttribute Relationship { get; } @@ -235,7 +265,7 @@ public static IncludeTreeNode CreateRoot(ResourceType resourceType) return new IncludeTreeNode(relationship); } - public ICollection EnsureChildren(ICollection relationships) + public ReadOnlyCollection EnsureChildren(RelationshipAttribute[] relationships) { foreach (RelationshipAttribute relationship in relationships) { @@ -246,7 +276,7 @@ public ICollection EnsureChildren(ICollection relationships.Contains(pair.Key)).Select(pair => pair.Value).ToList(); + return _children.Where(pair => relationships.Contains(pair.Key)).Select(pair => pair.Value).ToArray().AsReadOnly(); } public IncludeExpression ToExpression() @@ -255,7 +285,7 @@ public IncludeExpression ToExpression() if (element.Relationship is HiddenRootRelationshipAttribute) { - return element.Children.Any() ? new IncludeExpression(element.Children) : IncludeExpression.Empty; + return element.Children.Count > 0 ? new IncludeExpression(element.Children) : IncludeExpression.Empty; } return new IncludeExpression(ImmutableHashSet.Create(element)); @@ -277,7 +307,7 @@ private sealed class HiddenRootRelationshipAttribute : RelationshipAttribute { public HiddenRootRelationshipAttribute(ResourceType rightType) { - ArgumentGuard.NotNull(rightType); + ArgumentNullException.ThrowIfNull(rightType); RightType = rightType; PublicName = "<>"; diff --git a/src/JsonApiDotNetCore/Queries/Parsing/PaginationParser.cs b/src/JsonApiDotNetCore/Queries/Parsing/PaginationParser.cs index 059eb82a55..669fba7b9c 100644 --- a/src/JsonApiDotNetCore/Queries/Parsing/PaginationParser.cs +++ b/src/JsonApiDotNetCore/Queries/Parsing/PaginationParser.cs @@ -13,7 +13,7 @@ public class PaginationParser : QueryExpressionParser, IPaginationParser /// public PaginationQueryStringValueExpression Parse(string source, ResourceType resourceType) { - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(resourceType); Tokenize(source); @@ -26,13 +26,15 @@ public PaginationQueryStringValueExpression Parse(string source, ResourceType re protected virtual PaginationQueryStringValueExpression ParsePagination(ResourceType resourceType) { + ArgumentNullException.ThrowIfNull(resourceType); + ImmutableArray.Builder elementsBuilder = ImmutableArray.CreateBuilder(); PaginationElementQueryStringValueExpression element = ParsePaginationElement(resourceType); elementsBuilder.Add(element); - while (TokenStack.Any()) + while (TokenStack.Count > 0) { EatSingleCharacterToken(TokenKind.Comma); @@ -45,6 +47,8 @@ protected virtual PaginationQueryStringValueExpression ParsePagination(ResourceT protected virtual PaginationElementQueryStringValueExpression ParsePaginationElement(ResourceType resourceType) { + ArgumentNullException.ThrowIfNull(resourceType); + int position = GetNextTokenPositionOrEnd(); int? number = TryParseNumber(); diff --git a/src/JsonApiDotNetCore/Queries/Parsing/QueryExpressionParser.cs b/src/JsonApiDotNetCore/Queries/Parsing/QueryExpressionParser.cs index 5f1d3c1e89..772be38530 100644 --- a/src/JsonApiDotNetCore/Queries/Parsing/QueryExpressionParser.cs +++ b/src/JsonApiDotNetCore/Queries/Parsing/QueryExpressionParser.cs @@ -43,6 +43,8 @@ protected virtual void ValidateField(ResourceFieldAttribute field, int position) /// protected virtual void Tokenize(string source) { + ArgumentNullException.ThrowIfNull(source); + var tokenizer = new QueryTokenizer(source); TokenStack = new Stack(tokenizer.EnumerateTokens().Reverse()); _endOfSourcePosition = source.Length; @@ -54,8 +56,8 @@ protected virtual void Tokenize(string source) protected ResourceFieldChainExpression ParseFieldChain(FieldChainPattern pattern, FieldChainPatternMatchOptions options, ResourceType resourceType, string? alternativeErrorMessage) { - ArgumentGuard.NotNull(pattern); - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(pattern); + ArgumentNullException.ThrowIfNull(resourceType); int startPosition = GetNextTokenPositionOrEnd(); @@ -118,6 +120,8 @@ private string EatFieldChain(string? alternativeErrorMessage) /// protected void EatText(string text) { + ArgumentNullException.ThrowIfNull(text); + if (!TokenStack.TryPop(out Token? token) || token.Kind != TokenKind.Text || token.Value != text) { int position = token?.Position ?? GetNextTokenPositionOrEnd(); @@ -158,7 +162,7 @@ protected int GetNextTokenPositionOrEnd() /// protected int GetRelativePositionOfLastFieldInChain(ResourceFieldChainExpression fieldChain) { - ArgumentGuard.NotNull(fieldChain); + ArgumentNullException.ThrowIfNull(fieldChain); int position = 0; @@ -176,7 +180,7 @@ protected int GetRelativePositionOfLastFieldInChain(ResourceFieldChainExpression /// protected void AssertTokenStackIsEmpty() { - if (TokenStack.Any()) + if (TokenStack.Count > 0) { int position = GetNextTokenPositionOrEnd(); throw new QueryParseException("End of expression expected.", position); diff --git a/src/JsonApiDotNetCore/Queries/Parsing/QueryParseException.cs b/src/JsonApiDotNetCore/Queries/Parsing/QueryParseException.cs index 8136fb476e..4f63f45e24 100644 --- a/src/JsonApiDotNetCore/Queries/Parsing/QueryParseException.cs +++ b/src/JsonApiDotNetCore/Queries/Parsing/QueryParseException.cs @@ -28,7 +28,7 @@ public QueryParseException(string message, int position, Exception innerExceptio public string GetMessageWithPosition(string sourceText) { - ArgumentGuard.NotNull(sourceText); + ArgumentNullException.ThrowIfNull(sourceText); if (Position < 0) { diff --git a/src/JsonApiDotNetCore/Queries/Parsing/QueryStringParameterScopeParser.cs b/src/JsonApiDotNetCore/Queries/Parsing/QueryStringParameterScopeParser.cs index 2272b94caa..dfb98dc612 100644 --- a/src/JsonApiDotNetCore/Queries/Parsing/QueryStringParameterScopeParser.cs +++ b/src/JsonApiDotNetCore/Queries/Parsing/QueryStringParameterScopeParser.cs @@ -12,8 +12,8 @@ public class QueryStringParameterScopeParser : QueryExpressionParser, IQueryStri /// public QueryStringParameterScopeExpression Parse(string source, ResourceType resourceType, FieldChainPattern pattern, FieldChainPatternMatchOptions options) { - ArgumentGuard.NotNull(resourceType); - ArgumentGuard.NotNull(pattern); + ArgumentNullException.ThrowIfNull(resourceType); + ArgumentNullException.ThrowIfNull(pattern); Tokenize(source); @@ -27,6 +27,9 @@ public QueryStringParameterScopeExpression Parse(string source, ResourceType res protected virtual QueryStringParameterScopeExpression ParseQueryStringParameterScope(ResourceType resourceType, FieldChainPattern pattern, FieldChainPatternMatchOptions options) { + ArgumentNullException.ThrowIfNull(resourceType); + ArgumentNullException.ThrowIfNull(pattern); + int position = GetNextTokenPositionOrEnd(); if (!TokenStack.TryPop(out Token? token) || token.Kind != TokenKind.Text) diff --git a/src/JsonApiDotNetCore/Queries/Parsing/QueryTokenizer.cs b/src/JsonApiDotNetCore/Queries/Parsing/QueryTokenizer.cs index 9360d95be3..0c5f634375 100644 --- a/src/JsonApiDotNetCore/Queries/Parsing/QueryTokenizer.cs +++ b/src/JsonApiDotNetCore/Queries/Parsing/QueryTokenizer.cs @@ -1,4 +1,3 @@ -using System.Collections.ObjectModel; using System.Text; using JetBrains.Annotations; @@ -7,18 +6,17 @@ namespace JsonApiDotNetCore.Queries.Parsing; [PublicAPI] public sealed class QueryTokenizer { - public static readonly IReadOnlyDictionary SingleCharacterToTokenKinds = new ReadOnlyDictionary( - new Dictionary - { - ['('] = TokenKind.OpenParen, - [')'] = TokenKind.CloseParen, - ['['] = TokenKind.OpenBracket, - [']'] = TokenKind.CloseBracket, - ['.'] = TokenKind.Period, - [','] = TokenKind.Comma, - [':'] = TokenKind.Colon, - ['-'] = TokenKind.Minus - }); + public static readonly Dictionary SingleCharacterToTokenKinds = new() + { + ['('] = TokenKind.OpenParen, + [')'] = TokenKind.CloseParen, + ['['] = TokenKind.OpenBracket, + [']'] = TokenKind.CloseBracket, + ['.'] = TokenKind.Period, + [','] = TokenKind.Comma, + [':'] = TokenKind.Colon, + ['-'] = TokenKind.Minus + }; private readonly string _source; private readonly StringBuilder _textBuffer = new(); @@ -28,7 +26,7 @@ public sealed class QueryTokenizer public QueryTokenizer(string source) { - ArgumentGuard.NotNull(source); + ArgumentNullException.ThrowIfNull(source); _source = source; } diff --git a/src/JsonApiDotNetCore/Queries/Parsing/SortParser.cs b/src/JsonApiDotNetCore/Queries/Parsing/SortParser.cs index aaf636deca..e8df9b4a88 100644 --- a/src/JsonApiDotNetCore/Queries/Parsing/SortParser.cs +++ b/src/JsonApiDotNetCore/Queries/Parsing/SortParser.cs @@ -14,7 +14,7 @@ public class SortParser : QueryExpressionParser, ISortParser /// public SortExpression Parse(string source, ResourceType resourceType) { - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(resourceType); Tokenize(source); @@ -27,12 +27,14 @@ public SortExpression Parse(string source, ResourceType resourceType) protected virtual SortExpression ParseSort(ResourceType resourceType) { + ArgumentNullException.ThrowIfNull(resourceType); + SortElementExpression firstElement = ParseSortElement(resourceType); ImmutableArray.Builder elementsBuilder = ImmutableArray.CreateBuilder(); elementsBuilder.Add(firstElement); - while (TokenStack.Any()) + while (TokenStack.Count > 0) { EatSingleCharacterToken(TokenKind.Comma); @@ -45,6 +47,8 @@ protected virtual SortExpression ParseSort(ResourceType resourceType) protected virtual SortElementExpression ParseSortElement(ResourceType resourceType) { + ArgumentNullException.ThrowIfNull(resourceType); + bool isAscending = true; if (TokenStack.TryPeek(out Token? nextToken) && nextToken.Kind == TokenKind.Minus) @@ -95,14 +99,14 @@ protected virtual SortElementExpression ParseSortElement(ResourceType resourceTy protected virtual bool IsFunction(string name) { - ArgumentGuard.NotNullNorEmpty(name); + ArgumentException.ThrowIfNullOrEmpty(name); return name == Keywords.Count; } protected virtual FunctionExpression ParseFunction(ResourceType resourceType) { - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(resourceType); if (TokenStack.TryPeek(out Token? nextToken) && nextToken.Kind == TokenKind.Text) { @@ -134,6 +138,8 @@ private CountExpression ParseCount(ResourceType resourceType) protected override void ValidateField(ResourceFieldAttribute field, int position) { + ArgumentNullException.ThrowIfNull(field); + if (field is AttrAttribute attribute && !attribute.Capabilities.HasFlag(AttrCapabilities.AllowSort)) { throw new QueryParseException($"Sorting on attribute '{attribute.PublicName}' is not allowed.", position); diff --git a/src/JsonApiDotNetCore/Queries/Parsing/SparseFieldSetParser.cs b/src/JsonApiDotNetCore/Queries/Parsing/SparseFieldSetParser.cs index 7bbea5c082..9bf6a89daa 100644 --- a/src/JsonApiDotNetCore/Queries/Parsing/SparseFieldSetParser.cs +++ b/src/JsonApiDotNetCore/Queries/Parsing/SparseFieldSetParser.cs @@ -14,7 +14,7 @@ public class SparseFieldSetParser : QueryExpressionParser, ISparseFieldSetParser /// public SparseFieldSetExpression? Parse(string source, ResourceType resourceType) { - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(resourceType); Tokenize(source); @@ -27,9 +27,11 @@ public class SparseFieldSetParser : QueryExpressionParser, ISparseFieldSetParser protected virtual SparseFieldSetExpression? ParseSparseFieldSet(ResourceType resourceType) { + ArgumentNullException.ThrowIfNull(resourceType); + ImmutableHashSet.Builder fieldSetBuilder = ImmutableHashSet.CreateBuilder(); - while (TokenStack.Any()) + while (TokenStack.Count > 0) { if (fieldSetBuilder.Count > 0) { @@ -43,11 +45,13 @@ public class SparseFieldSetParser : QueryExpressionParser, ISparseFieldSetParser fieldSetBuilder.Add(nextField); } - return fieldSetBuilder.Any() ? new SparseFieldSetExpression(fieldSetBuilder.ToImmutable()) : null; + return fieldSetBuilder.Count > 0 ? new SparseFieldSetExpression(fieldSetBuilder.ToImmutable()) : null; } protected override void ValidateField(ResourceFieldAttribute field, int position) { + ArgumentNullException.ThrowIfNull(field); + if (field.IsViewBlocked()) { string kind = field is AttrAttribute ? "attribute" : "relationship"; diff --git a/src/JsonApiDotNetCore/Queries/Parsing/SparseFieldTypeParser.cs b/src/JsonApiDotNetCore/Queries/Parsing/SparseFieldTypeParser.cs index e24ce9f90e..00c5c6a525 100644 --- a/src/JsonApiDotNetCore/Queries/Parsing/SparseFieldTypeParser.cs +++ b/src/JsonApiDotNetCore/Queries/Parsing/SparseFieldTypeParser.cs @@ -11,7 +11,7 @@ public class SparseFieldTypeParser : QueryExpressionParser, ISparseFieldTypePars public SparseFieldTypeParser(IResourceGraph resourceGraph) { - ArgumentGuard.NotNull(resourceGraph); + ArgumentNullException.ThrowIfNull(resourceGraph); _resourceGraph = resourceGraph; } diff --git a/src/JsonApiDotNetCore/Queries/QueryLayer.cs b/src/JsonApiDotNetCore/Queries/QueryLayer.cs index 3a755d519b..1ff8e34dcf 100644 --- a/src/JsonApiDotNetCore/Queries/QueryLayer.cs +++ b/src/JsonApiDotNetCore/Queries/QueryLayer.cs @@ -21,7 +21,7 @@ public sealed class QueryLayer public QueryLayer(ResourceType resourceType) { - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(resourceType); ResourceType = resourceType; } @@ -42,7 +42,7 @@ internal void WriteLayer(IndentingStringWriter writer, string? prefix) using (writer.Indent()) { - if (Include != null && Include.Elements.Any()) + if (Include is { Elements.Count: > 0 }) { writer.WriteLine($"{nameof(Include)}: {Include}"); } diff --git a/src/JsonApiDotNetCore/Queries/QueryLayerComposer.cs b/src/JsonApiDotNetCore/Queries/QueryLayerComposer.cs index 1c4ca77119..f7843b12cf 100644 --- a/src/JsonApiDotNetCore/Queries/QueryLayerComposer.cs +++ b/src/JsonApiDotNetCore/Queries/QueryLayerComposer.cs @@ -1,4 +1,5 @@ using System.Collections.Immutable; +using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; using JetBrains.Annotations; using JsonApiDotNetCore.Configuration; @@ -13,8 +14,7 @@ namespace JsonApiDotNetCore.Queries; [PublicAPI] public class QueryLayerComposer : IQueryLayerComposer { - private readonly CollectionConverter _collectionConverter = new(); - private readonly IEnumerable _constraintProviders; + private readonly IQueryConstraintProvider[] _constraintProviders; private readonly IResourceDefinitionAccessor _resourceDefinitionAccessor; private readonly IJsonApiOptions _options; private readonly IPaginationContext _paginationContext; @@ -26,15 +26,15 @@ public QueryLayerComposer(IEnumerable constraintProvid IJsonApiOptions options, IPaginationContext paginationContext, ITargetedFields targetedFields, IEvaluatedIncludeCache evaluatedIncludeCache, ISparseFieldSetCache sparseFieldSetCache) { - ArgumentGuard.NotNull(constraintProviders); - ArgumentGuard.NotNull(resourceDefinitionAccessor); - ArgumentGuard.NotNull(options); - ArgumentGuard.NotNull(paginationContext); - ArgumentGuard.NotNull(targetedFields); - ArgumentGuard.NotNull(evaluatedIncludeCache); - ArgumentGuard.NotNull(sparseFieldSetCache); - - _constraintProviders = constraintProviders; + ArgumentNullException.ThrowIfNull(constraintProviders); + ArgumentNullException.ThrowIfNull(resourceDefinitionAccessor); + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(paginationContext); + ArgumentNullException.ThrowIfNull(targetedFields); + ArgumentNullException.ThrowIfNull(evaluatedIncludeCache); + ArgumentNullException.ThrowIfNull(sparseFieldSetCache); + + _constraintProviders = constraintProviders as IQueryConstraintProvider[] ?? constraintProviders.ToArray(); _resourceDefinitionAccessor = resourceDefinitionAccessor; _options = options; _paginationContext = paginationContext; @@ -46,16 +46,16 @@ public QueryLayerComposer(IEnumerable constraintProvid /// public FilterExpression? GetPrimaryFilterFromConstraints(ResourceType primaryResourceType) { - ExpressionInScope[] constraints = _constraintProviders.SelectMany(provider => provider.GetConstraints()).ToArray(); - // @formatter:wrap_chained_method_calls chop_always // @formatter:wrap_before_first_method_call true - FilterExpression[] filtersInTopScope = constraints + ReadOnlyCollection filtersInTopScope = _constraintProviders + .SelectMany(provider => provider.GetConstraints()) .Where(constraint => constraint.Scope == null) .Select(constraint => constraint.Expression) .OfType() - .ToArray(); + .ToArray() + .AsReadOnly(); // @formatter:wrap_before_first_method_call restore // @formatter:wrap_chained_method_calls restore @@ -66,7 +66,7 @@ public QueryLayerComposer(IEnumerable constraintProvid /// public FilterExpression? GetSecondaryFilterFromConstraints([DisallowNull] TId primaryId, HasManyAttribute hasManyRelationship) { - ArgumentGuard.NotNull(hasManyRelationship); + ArgumentNullException.ThrowIfNull(hasManyRelationship); if (hasManyRelationship.InverseNavigationProperty == null) { @@ -81,37 +81,44 @@ public QueryLayerComposer(IEnumerable constraintProvid return null; } - ExpressionInScope[] constraints = _constraintProviders.SelectMany(provider => provider.GetConstraints()).ToArray(); - // @formatter:wrap_chained_method_calls chop_always // @formatter:wrap_before_first_method_call true - FilterExpression[] filtersInSecondaryScope = constraints + ReadOnlyCollection filtersInSecondaryScope = _constraintProviders + .SelectMany(provider => provider.GetConstraints()) .Where(constraint => constraint.Scope == null) .Select(constraint => constraint.Expression) .OfType() - .ToArray(); + .ToArray() + .AsReadOnly(); // @formatter:wrap_before_first_method_call restore // @formatter:wrap_chained_method_calls restore FilterExpression? primaryFilter = GetFilter(Array.Empty(), hasManyRelationship.LeftType); - FilterExpression? secondaryFilter = GetFilter(filtersInSecondaryScope, hasManyRelationship.RightType); - FilterExpression inverseFilter = GetInverseRelationshipFilter(primaryId, hasManyRelationship, inverseRelationship); + if (primaryFilter != null && inverseRelationship is HasOneAttribute) + { + // We can't lift the field chains in a primary filter, because there's no way for a custom filter expression to express + // the scope of its chains. See https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/1671. + return null; + } + + FilterExpression? secondaryFilter = GetFilter(filtersInSecondaryScope, hasManyRelationship.RightType); + FilterExpression inverseFilter = GetInverseRelationshipFilter(primaryId, primaryFilter, hasManyRelationship, inverseRelationship); - return LogicalExpression.Compose(LogicalOperator.And, inverseFilter, primaryFilter, secondaryFilter); + return LogicalExpression.Compose(LogicalOperator.And, inverseFilter, secondaryFilter); } - private static FilterExpression GetInverseRelationshipFilter([DisallowNull] TId primaryId, HasManyAttribute relationship, - RelationshipAttribute inverseRelationship) + private static FilterExpression GetInverseRelationshipFilter([DisallowNull] TId primaryId, FilterExpression? primaryFilter, + HasManyAttribute relationship, RelationshipAttribute inverseRelationship) { return inverseRelationship is HasManyAttribute hasManyInverseRelationship - ? GetInverseHasManyRelationshipFilter(primaryId, relationship, hasManyInverseRelationship) + ? GetInverseHasManyRelationshipFilter(primaryId, primaryFilter, relationship, hasManyInverseRelationship) : GetInverseHasOneRelationshipFilter(primaryId, relationship, (HasOneAttribute)inverseRelationship); } - private static FilterExpression GetInverseHasOneRelationshipFilter([DisallowNull] TId primaryId, HasManyAttribute relationship, + private static ComparisonExpression GetInverseHasOneRelationshipFilter([DisallowNull] TId primaryId, HasManyAttribute relationship, HasOneAttribute inverseRelationship) { AttrAttribute idAttribute = GetIdAttribute(relationship.LeftType); @@ -120,22 +127,23 @@ private static FilterExpression GetInverseHasOneRelationshipFilter([Disallo return new ComparisonExpression(ComparisonOperator.Equals, idChain, new LiteralConstantExpression(primaryId)); } - private static FilterExpression GetInverseHasManyRelationshipFilter([DisallowNull] TId primaryId, HasManyAttribute relationship, - HasManyAttribute inverseRelationship) + private static HasExpression GetInverseHasManyRelationshipFilter([DisallowNull] TId primaryId, FilterExpression? primaryFilter, + HasManyAttribute relationship, HasManyAttribute inverseRelationship) { AttrAttribute idAttribute = GetIdAttribute(relationship.LeftType); var idChain = new ResourceFieldChainExpression(ImmutableArray.Create(idAttribute)); var idComparison = new ComparisonExpression(ComparisonOperator.Equals, idChain, new LiteralConstantExpression(primaryId)); - return new HasExpression(new ResourceFieldChainExpression(inverseRelationship), idComparison); + FilterExpression filter = LogicalExpression.Compose(LogicalOperator.And, idComparison, primaryFilter)!; + return new HasExpression(new ResourceFieldChainExpression(inverseRelationship), filter); } /// public QueryLayer ComposeFromConstraints(ResourceType requestResourceType) { - ArgumentGuard.NotNull(requestResourceType); + ArgumentNullException.ThrowIfNull(requestResourceType); - ExpressionInScope[] constraints = _constraintProviders.SelectMany(provider => provider.GetConstraints()).ToArray(); + ImmutableArray constraints = [.. _constraintProviders.SelectMany(provider => provider.GetConstraints())]; QueryLayer topLayer = ComposeTopLayer(constraints, requestResourceType); topLayer.Include = ComposeChildren(topLayer, constraints); @@ -145,17 +153,18 @@ public QueryLayer ComposeFromConstraints(ResourceType requestResourceType) return topLayer; } - private QueryLayer ComposeTopLayer(IEnumerable constraints, ResourceType resourceType) + private QueryLayer ComposeTopLayer(ImmutableArray constraints, ResourceType resourceType) { using IDisposable _ = CodeTimingSessionManager.Current.Measure("Top-level query composition"); // @formatter:wrap_chained_method_calls chop_always // @formatter:wrap_before_first_method_call true - QueryExpression[] expressionsInTopScope = constraints + ReadOnlyCollection expressionsInTopScope = constraints .Where(constraint => constraint.Scope == null) .Select(constraint => constraint.Expression) - .ToArray(); + .ToArray() + .AsReadOnly(); // @formatter:wrap_before_first_method_call restore // @formatter:wrap_chained_method_calls restore @@ -173,7 +182,7 @@ private QueryLayer ComposeTopLayer(IEnumerable constraints, R }; } - private IncludeExpression ComposeChildren(QueryLayer topLayer, ICollection constraints) + private IncludeExpression ComposeChildren(QueryLayer topLayer, ImmutableArray constraints) { using IDisposable _ = CodeTimingSessionManager.Current.Measure("Nested query composition"); @@ -189,15 +198,16 @@ private IncludeExpression ComposeChildren(QueryLayer topLayer, ICollection includeElements = ProcessIncludeSet(include.Elements, topLayer, new List(), constraints); + IImmutableSet includeElements = + ProcessIncludeSet(include.Elements, topLayer, ImmutableArray.Empty, constraints); return !ReferenceEquals(includeElements, include.Elements) - ? includeElements.Any() ? new IncludeExpression(includeElements) : IncludeExpression.Empty + ? includeElements.Count > 0 ? new IncludeExpression(includeElements) : IncludeExpression.Empty : include; } private IImmutableSet ProcessIncludeSet(IImmutableSet includeElements, QueryLayer parentLayer, - ICollection parentRelationshipChain, ICollection constraints) + ImmutableArray parentRelationshipChain, ImmutableArray constraints) { IImmutableSet includeElementsEvaluated = GetIncludeElements(includeElements, parentLayer.ResourceType); @@ -206,22 +216,20 @@ private IImmutableSet ProcessIncludeSet(IImmutableSet< foreach (IncludeElementExpression includeElement in includeElementsEvaluated) { parentLayer.Selection ??= new FieldSelection(); - FieldSelectors selectors = parentLayer.Selection.GetOrCreateSelectors(parentLayer.ResourceType); + FieldSelectors selectors = parentLayer.Selection.GetOrCreateSelectors(includeElement.Relationship.LeftType); if (!selectors.ContainsField(includeElement.Relationship)) { - var relationshipChain = new List(parentRelationshipChain) - { - includeElement.Relationship - }; + ImmutableArray relationshipChain = parentRelationshipChain.Add(includeElement.Relationship); // @formatter:wrap_chained_method_calls chop_always // @formatter:wrap_before_first_method_call true - QueryExpression[] expressionsInCurrentScope = constraints + ReadOnlyCollection expressionsInCurrentScope = constraints .Where(constraint => constraint.Scope != null && constraint.Scope.Fields.SequenceEqual(relationshipChain)) .Select(constraint => constraint.Expression) - .ToArray(); + .ToArray() + .AsReadOnly(); // @formatter:wrap_before_first_method_call restore // @formatter:wrap_chained_method_calls restore @@ -248,11 +256,11 @@ private IImmutableSet ProcessIncludeSet(IImmutableSet< } } - return !updatesInChildren.Any() ? includeElementsEvaluated : ApplyIncludeElementUpdates(includeElementsEvaluated, updatesInChildren); + return updatesInChildren.Count == 0 ? includeElementsEvaluated : ApplyIncludeElementUpdates(includeElementsEvaluated, updatesInChildren); } - private static IImmutableSet ApplyIncludeElementUpdates(IImmutableSet includeElements, - IDictionary> updatesInChildren) + private static ImmutableHashSet ApplyIncludeElementUpdates(IImmutableSet includeElements, + Dictionary> updatesInChildren) { ImmutableHashSet.Builder newElementsBuilder = ImmutableHashSet.CreateBuilder(); newElementsBuilder.UnionWith(includeElements); @@ -269,7 +277,7 @@ private static IImmutableSet ApplyIncludeElementUpdate /// public QueryLayer ComposeForGetById([DisallowNull] TId id, ResourceType primaryResourceType, TopFieldSelection fieldSelection) { - ArgumentGuard.NotNull(primaryResourceType); + ArgumentNullException.ThrowIfNull(primaryResourceType); AttrAttribute idAttribute = GetIdAttribute(primaryResourceType); @@ -297,7 +305,7 @@ public QueryLayer ComposeForGetById([DisallowNull] TId id, ResourceType pri /// public QueryLayer ComposeSecondaryLayerForRelationship(ResourceType secondaryResourceType) { - ArgumentGuard.NotNull(secondaryResourceType); + ArgumentNullException.ThrowIfNull(secondaryResourceType); QueryLayer secondaryLayer = ComposeFromConstraints(secondaryResourceType); secondaryLayer.Selection = GetSelectionForRelationship(secondaryResourceType); @@ -321,9 +329,9 @@ private FieldSelection GetSelectionForRelationship(ResourceType secondaryResourc public QueryLayer WrapLayerForSecondaryEndpoint(QueryLayer secondaryLayer, ResourceType primaryResourceType, [DisallowNull] TId primaryId, RelationshipAttribute relationship) { - ArgumentGuard.NotNull(secondaryLayer); - ArgumentGuard.NotNull(primaryResourceType); - ArgumentGuard.NotNull(relationship); + ArgumentNullException.ThrowIfNull(secondaryLayer); + ArgumentNullException.ThrowIfNull(primaryResourceType); + ArgumentNullException.ThrowIfNull(relationship); IncludeExpression? innerInclude = secondaryLayer.Include; secondaryLayer.Include = null; @@ -360,18 +368,18 @@ private IncludeExpression RewriteIncludeForSecondaryEndpoint(IncludeExpression? return new IncludeExpression(ImmutableHashSet.Create(parentElement)); } - private FilterExpression? CreateFilterByIds(IReadOnlyCollection ids, AttrAttribute idAttribute, FilterExpression? existingFilter) + private FilterExpression? CreateFilterByIds(TId[] ids, AttrAttribute idAttribute, FilterExpression? existingFilter) { var idChain = new ResourceFieldChainExpression(idAttribute); FilterExpression? filter = null; - if (ids.Count == 1) + if (ids.Length == 1) { var constant = new LiteralConstantExpression(ids.Single()!); filter = new ComparisonExpression(ComparisonOperator.Equals, idChain, constant); } - else if (ids.Count > 1) + else if (ids.Length > 1) { ImmutableHashSet constants = ids.Select(id => new LiteralConstantExpression(id!)).ToImmutableHashSet(); filter = new AnyExpression(idChain, constants); @@ -383,15 +391,15 @@ private IncludeExpression RewriteIncludeForSecondaryEndpoint(IncludeExpression? /// public QueryLayer ComposeForUpdate([DisallowNull] TId id, ResourceType primaryResourceType) { - ArgumentGuard.NotNull(primaryResourceType); + ArgumentNullException.ThrowIfNull(primaryResourceType); - IImmutableSet includeElements = _targetedFields.Relationships + ImmutableHashSet includeElements = _targetedFields.Relationships .Select(relationship => new IncludeElementExpression(relationship)).ToImmutableHashSet(); AttrAttribute primaryIdAttribute = GetIdAttribute(primaryResourceType); - QueryLayer primaryLayer = ComposeTopLayer(Array.Empty(), primaryResourceType); - primaryLayer.Include = includeElements.Any() ? new IncludeExpression(includeElements) : IncludeExpression.Empty; + QueryLayer primaryLayer = ComposeTopLayer(ImmutableArray.Empty, primaryResourceType); + primaryLayer.Include = includeElements.Count > 0 ? new IncludeExpression(includeElements) : IncludeExpression.Empty; primaryLayer.Sort = null; primaryLayer.Pagination = null; primaryLayer.Filter = CreateFilterByIds([id], primaryIdAttribute, primaryLayer.Filter); @@ -403,14 +411,14 @@ public QueryLayer ComposeForUpdate([DisallowNull] TId id, ResourceType prim /// public IEnumerable<(QueryLayer, RelationshipAttribute)> ComposeForGetTargetedSecondaryResourceIds(IIdentifiable primaryResource) { - ArgumentGuard.NotNull(primaryResource); + ArgumentNullException.ThrowIfNull(primaryResource); foreach (RelationshipAttribute relationship in _targetedFields.Relationships) { object? rightValue = relationship.GetValue(primaryResource); - HashSet rightResourceIds = _collectionConverter.ExtractResources(rightValue).ToHashSet(IdentifiableComparer.Instance); + HashSet rightResourceIds = CollectionConverter.Instance.ExtractResources(rightValue).ToHashSet(IdentifiableComparer.Instance); - if (rightResourceIds.Any()) + if (rightResourceIds.Count > 0) { QueryLayer queryLayer = ComposeForGetRelationshipRightIds(relationship, rightResourceIds); yield return (queryLayer, relationship); @@ -421,12 +429,12 @@ public QueryLayer ComposeForUpdate([DisallowNull] TId id, ResourceType prim /// public QueryLayer ComposeForGetRelationshipRightIds(RelationshipAttribute relationship, ICollection rightResourceIds) { - ArgumentGuard.NotNull(relationship); - ArgumentGuard.NotNull(rightResourceIds); + ArgumentNullException.ThrowIfNull(relationship); + ArgumentNullException.ThrowIfNull(rightResourceIds); AttrAttribute rightIdAttribute = GetIdAttribute(relationship.RightType); - HashSet typedIds = rightResourceIds.Select(resource => resource.GetTypedId()).ToHashSet(); + object[] typedIds = rightResourceIds.Select(resource => resource.GetTypedId()).ToArray(); FilterExpression? baseFilter = GetFilter(Array.Empty(), relationship.RightType); FilterExpression? filter = CreateFilterByIds(typedIds, rightIdAttribute, baseFilter); @@ -446,12 +454,12 @@ public QueryLayer ComposeForGetRelationshipRightIds(RelationshipAttribute relati /// public QueryLayer ComposeForHasMany(HasManyAttribute hasManyRelationship, [DisallowNull] TId leftId, ICollection rightResourceIds) { - ArgumentGuard.NotNull(hasManyRelationship); - ArgumentGuard.NotNull(rightResourceIds); + ArgumentNullException.ThrowIfNull(hasManyRelationship); + ArgumentNullException.ThrowIfNull(rightResourceIds); AttrAttribute leftIdAttribute = GetIdAttribute(hasManyRelationship.LeftType); AttrAttribute rightIdAttribute = GetIdAttribute(hasManyRelationship.RightType); - HashSet rightTypedIds = rightResourceIds.Select(resource => resource.GetTypedId()).ToHashSet(); + object[] rightTypedIds = rightResourceIds.Select(resource => resource.GetTypedId()).ToArray(); FilterExpression? leftFilter = CreateFilterByIds([leftId], leftIdAttribute, null); FilterExpression? rightFilter = CreateFilterByIds(rightTypedIds, rightIdAttribute, null); @@ -482,15 +490,16 @@ public QueryLayer ComposeForHasMany(HasManyAttribute hasManyRelationship, [ protected virtual IImmutableSet GetIncludeElements(IImmutableSet includeElements, ResourceType resourceType) { - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(includeElements); + ArgumentNullException.ThrowIfNull(resourceType); return _resourceDefinitionAccessor.OnApplyIncludes(resourceType, includeElements); } protected virtual FilterExpression? GetFilter(IReadOnlyCollection expressionsInScope, ResourceType resourceType) { - ArgumentGuard.NotNull(expressionsInScope); - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(expressionsInScope); + ArgumentNullException.ThrowIfNull(resourceType); FilterExpression[] filters = expressionsInScope.OfType().ToArray(); FilterExpression? filter = LogicalExpression.Compose(LogicalOperator.And, filters); @@ -500,8 +509,8 @@ protected virtual IImmutableSet GetIncludeElements(IIm protected virtual SortExpression GetSort(IReadOnlyCollection expressionsInScope, ResourceType resourceType) { - ArgumentGuard.NotNull(expressionsInScope); - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(expressionsInScope); + ArgumentNullException.ThrowIfNull(resourceType); SortExpression? sort = expressionsInScope.OfType().FirstOrDefault(); @@ -519,8 +528,8 @@ protected virtual SortExpression GetSort(IReadOnlyCollection ex protected virtual PaginationExpression GetPagination(IReadOnlyCollection expressionsInScope, ResourceType resourceType) { - ArgumentGuard.NotNull(expressionsInScope); - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(expressionsInScope); + ArgumentNullException.ThrowIfNull(resourceType); PaginationExpression? pagination = expressionsInScope.OfType().FirstOrDefault(); @@ -535,7 +544,7 @@ protected virtual PaginationExpression GetPagination(IReadOnlyCollection fieldSet = _sparseFieldSetCache.GetSparseFieldSetForQuery(nextType); - if (!fieldSet.Any()) + if (fieldSet.Count == 0) { continue; } diff --git a/src/JsonApiDotNetCore/Queries/QueryableBuilding/IncludeClauseBuilder.cs b/src/JsonApiDotNetCore/Queries/QueryableBuilding/IncludeClauseBuilder.cs index 3bd19eb21f..115202b138 100644 --- a/src/JsonApiDotNetCore/Queries/QueryableBuilding/IncludeClauseBuilder.cs +++ b/src/JsonApiDotNetCore/Queries/QueryableBuilding/IncludeClauseBuilder.cs @@ -14,7 +14,7 @@ public class IncludeClauseBuilder : QueryClauseBuilder, IIncludeClauseBuilder public virtual Expression ApplyInclude(IncludeExpression include, QueryClauseBuilderContext context) { - ArgumentGuard.NotNull(include); + ArgumentNullException.ThrowIfNull(include); return Visit(include, context); } @@ -34,7 +34,7 @@ public override Expression VisitInclude(IncludeExpression expression, QueryClaus return ToExpression(context.Source, context.LambdaScope.Parameter.Type, propertyPaths); } - private static void ProcessRelationshipChain(ResourceFieldChainExpression chain, ISet outputPropertyPaths) + private static void ProcessRelationshipChain(ResourceFieldChainExpression chain, HashSet outputPropertyPaths) { string? path = null; @@ -71,7 +71,7 @@ private static Expression ToExpression(Expression source, Type entityType, HashS return expression; } - private static Expression IncludeExtensionMethodCall(Expression source, Type entityType, string navigationPropertyPath) + private static MethodCallExpression IncludeExtensionMethodCall(Expression source, Type entityType, string navigationPropertyPath) { Expression navigationExpression = Expression.Constant(navigationPropertyPath); diff --git a/src/JsonApiDotNetCore/Queries/QueryableBuilding/LambdaScope.cs b/src/JsonApiDotNetCore/Queries/QueryableBuilding/LambdaScope.cs index 3f60ef8e55..6e94e459b5 100644 --- a/src/JsonApiDotNetCore/Queries/QueryableBuilding/LambdaScope.cs +++ b/src/JsonApiDotNetCore/Queries/QueryableBuilding/LambdaScope.cs @@ -30,9 +30,9 @@ private LambdaScope(LambdaScopeFactory owner, ParameterExpression parameter, Exp internal static LambdaScope Create(LambdaScopeFactory owner, Type elementType, string parameterName, Expression? accessorExpression = null) { - ArgumentGuard.NotNull(owner); - ArgumentGuard.NotNull(elementType); - ArgumentGuard.NotNullNorEmpty(parameterName); + ArgumentNullException.ThrowIfNull(owner); + ArgumentNullException.ThrowIfNull(elementType); + ArgumentException.ThrowIfNullOrEmpty(parameterName); ParameterExpression parameter = Expression.Parameter(elementType, parameterName); Expression accessor = accessorExpression ?? parameter; @@ -42,7 +42,7 @@ internal static LambdaScope Create(LambdaScopeFactory owner, Type elementType, s public LambdaScope WithAccessor(Expression accessorExpression) { - ArgumentGuard.NotNull(accessorExpression); + ArgumentNullException.ThrowIfNull(accessorExpression); return new LambdaScope(_owner, Parameter, accessorExpression); } diff --git a/src/JsonApiDotNetCore/Queries/QueryableBuilding/LambdaScopeFactory.cs b/src/JsonApiDotNetCore/Queries/QueryableBuilding/LambdaScopeFactory.cs index 257906b69f..3d9e87dc01 100644 --- a/src/JsonApiDotNetCore/Queries/QueryableBuilding/LambdaScopeFactory.cs +++ b/src/JsonApiDotNetCore/Queries/QueryableBuilding/LambdaScopeFactory.cs @@ -17,7 +17,7 @@ public sealed class LambdaScopeFactory /// public LambdaScope CreateScope(Type elementType, Expression? accessorExpression = null) { - ArgumentGuard.NotNull(elementType); + ArgumentNullException.ThrowIfNull(elementType); string parameterName = elementType.Name.Camelize(); parameterName = EnsureUniqueName(parameterName); @@ -48,7 +48,7 @@ private string EnsureUniqueName(string name) internal void Release(LambdaScope lambdaScope) { - ArgumentGuard.NotNull(lambdaScope); + ArgumentNullException.ThrowIfNull(lambdaScope); _namesInScope.Remove(lambdaScope.Parameter.Name!); } diff --git a/src/JsonApiDotNetCore/Queries/QueryableBuilding/OrderClauseBuilder.cs b/src/JsonApiDotNetCore/Queries/QueryableBuilding/OrderClauseBuilder.cs index 93dd7c53d1..6528d63ff8 100644 --- a/src/JsonApiDotNetCore/Queries/QueryableBuilding/OrderClauseBuilder.cs +++ b/src/JsonApiDotNetCore/Queries/QueryableBuilding/OrderClauseBuilder.cs @@ -10,7 +10,7 @@ public class OrderClauseBuilder : QueryClauseBuilder, IOrderClauseBuilder { public virtual Expression ApplyOrderBy(SortExpression expression, QueryClauseBuilderContext context) { - ArgumentGuard.NotNull(expression); + ArgumentNullException.ThrowIfNull(expression); return Visit(expression, context); } @@ -54,7 +54,7 @@ private static string GetOperationName(bool isAscending, QueryClauseBuilderConte return isAscending ? "OrderBy" : "OrderByDescending"; } - private static Expression ExtensionMethodCall(Expression source, string operationName, Type keyType, LambdaExpression keySelector, + private static MethodCallExpression ExtensionMethodCall(Expression source, string operationName, Type keyType, LambdaExpression keySelector, QueryClauseBuilderContext context) { Type[] typeArguments = diff --git a/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryClauseBuilder.cs b/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryClauseBuilder.cs index 4e2743fa02..b34e5b56cd 100644 --- a/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryClauseBuilder.cs +++ b/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryClauseBuilder.cs @@ -19,7 +19,7 @@ public override Expression VisitCount(CountExpression expression, QueryClauseBui { Expression collectionExpression = Visit(expression.TargetCollection, context); - Expression? propertyExpression = GetCollectionCount(collectionExpression); + MemberExpression? propertyExpression = GetCollectionCount(collectionExpression); if (propertyExpression == null) { @@ -29,7 +29,7 @@ public override Expression VisitCount(CountExpression expression, QueryClauseBui return propertyExpression; } - private static Expression? GetCollectionCount(Expression? collectionExpression) + private static MemberExpression? GetCollectionCount(Expression? collectionExpression) { if (collectionExpression != null) { diff --git a/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryClauseBuilderContext.cs b/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryClauseBuilderContext.cs index 05cccf7943..6344b91cb8 100644 --- a/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryClauseBuilderContext.cs +++ b/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryClauseBuilderContext.cs @@ -54,13 +54,14 @@ public sealed class QueryClauseBuilderContext public QueryClauseBuilderContext(Expression source, ResourceType resourceType, Type extensionType, IReadOnlyModel entityModel, LambdaScopeFactory lambdaScopeFactory, LambdaScope lambdaScope, IQueryableBuilder queryableBuilder, object? state) { - ArgumentGuard.NotNull(source); - ArgumentGuard.NotNull(resourceType); - ArgumentGuard.NotNull(extensionType); - ArgumentGuard.NotNull(entityModel); - ArgumentGuard.NotNull(lambdaScopeFactory); - ArgumentGuard.NotNull(lambdaScope); - ArgumentGuard.NotNull(queryableBuilder); + ArgumentNullException.ThrowIfNull(source); + ArgumentNullException.ThrowIfNull(resourceType); + ArgumentNullException.ThrowIfNull(extensionType); + ArgumentNullException.ThrowIfNull(entityModel); + ArgumentNullException.ThrowIfNull(lambdaScopeFactory); + ArgumentNullException.ThrowIfNull(lambdaScope); + ArgumentNullException.ThrowIfNull(queryableBuilder); + AssertSameType(source.Type, resourceType); Source = source; ResourceType = resourceType; @@ -72,16 +73,27 @@ public QueryClauseBuilderContext(Expression source, ResourceType resourceType, T State = state; } + private static void AssertSameType(Type sourceType, ResourceType resourceType) + { + Type? sourceElementType = CollectionConverter.Instance.FindCollectionElementType(sourceType); + + if (sourceElementType != resourceType.ClrType) + { + throw new InvalidOperationException( + $"Internal error: Mismatch between expression type '{sourceElementType?.Name}' and resource type '{resourceType.ClrType.Name}'."); + } + } + public QueryClauseBuilderContext WithSource(Expression source) { - ArgumentGuard.NotNull(source); + ArgumentNullException.ThrowIfNull(source); return new QueryClauseBuilderContext(source, ResourceType, ExtensionType, EntityModel, LambdaScopeFactory, LambdaScope, QueryableBuilder, State); } public QueryClauseBuilderContext WithLambdaScope(LambdaScope lambdaScope) { - ArgumentGuard.NotNull(lambdaScope); + ArgumentNullException.ThrowIfNull(lambdaScope); return new QueryClauseBuilderContext(Source, ResourceType, ExtensionType, EntityModel, LambdaScopeFactory, lambdaScope, QueryableBuilder, State); } diff --git a/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryLayerIncludeConverter.cs b/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryLayerIncludeConverter.cs index 9c4351f0f7..5d4eec3e31 100644 --- a/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryLayerIncludeConverter.cs +++ b/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryLayerIncludeConverter.cs @@ -12,7 +12,7 @@ public sealed class QueryLayerIncludeConverter : QueryExpressionVisitor 1 - ? CreateLambdaBodyInitializerForTypeHierarchy(selection, resourceType, concreteEntityTypes, lambdaScope, context) - : CreateLambdaBodyInitializerForSingleType(selection, resourceType, lambdaScope, context); + ? CreateLambdaBodyInitializerForTypeHierarchy(selection, resourceType, concreteEntityTypes, context) + : CreateLambdaBodyInitializerForSingleType(selection, resourceType, context); if (!lambdaAccessorRequiresTestForNull) { return bodyInitializer; } - return TestForNull(lambdaScope.Accessor, bodyInitializer); + return TestForNull(context.LambdaScope.Accessor, bodyInitializer); + } + + private static void AssertSameType(Type lambdaAccessorType, ResourceType resourceType) + { + if (lambdaAccessorType != resourceType.ClrType) + { + throw new InvalidOperationException( + $"Internal error: Mismatch between lambda accessor type '{lambdaAccessorType.Name}' and resource type '{resourceType.ClrType.Name}'."); + } } private Expression CreateLambdaBodyInitializerForTypeHierarchy(FieldSelection selection, ResourceType baseResourceType, - IEnumerable concreteEntityTypes, LambdaScope lambdaScope, QueryClauseBuilderContext context) + IEnumerable concreteEntityTypes, QueryClauseBuilderContext context) { IReadOnlySet resourceTypes = selection.GetResourceTypes(); - Expression rootCondition = lambdaScope.Accessor; + Expression rootCondition = context.LambdaScope.Accessor; foreach (IReadOnlyEntityType entityType in concreteEntityTypes) { @@ -71,17 +81,17 @@ private Expression CreateLambdaBodyInitializerForTypeHierarchy(FieldSelection se if (!fieldSelectors.IsEmpty) { - ICollection propertySelectors = + Dictionary.ValueCollection propertySelectors = ToPropertySelectors(fieldSelectors, resourceType, entityType.ClrType, context.EntityModel); - MemberBinding[] propertyAssignments = propertySelectors.Select(selector => CreatePropertyAssignment(selector, lambdaScope, context)) + MemberBinding[] propertyAssignments = propertySelectors.Select(selector => CreatePropertyAssignment(selector, context)) .Cast().ToArray(); NewExpression createInstance = _resourceFactory.CreateNewExpression(entityType.ClrType); MemberInitExpression memberInit = Expression.MemberInit(createInstance, propertyAssignments); UnaryExpression castToBaseType = Expression.Convert(memberInit, baseResourceType.ClrType); - BinaryExpression typeCheck = CreateRuntimeTypeCheck(lambdaScope, entityType.ClrType); + BinaryExpression typeCheck = CreateRuntimeTypeCheck(context.LambdaScope, entityType.ClrType); rootCondition = Expression.Condition(typeCheck, castToBaseType, rootCondition); } } @@ -101,21 +111,21 @@ private static BinaryExpression CreateRuntimeTypeCheck(LambdaScope lambdaScope, return Expression.MakeBinary(ExpressionType.Equal, getTypeCall, concreteTypeConstant, false, TypeOpEqualityMethod); } - private Expression CreateLambdaBodyInitializerForSingleType(FieldSelection selection, ResourceType resourceType, LambdaScope lambdaScope, + private MemberInitExpression CreateLambdaBodyInitializerForSingleType(FieldSelection selection, ResourceType resourceType, QueryClauseBuilderContext context) { FieldSelectors fieldSelectors = selection.GetOrCreateSelectors(resourceType); - ICollection propertySelectors = ToPropertySelectors(fieldSelectors, resourceType, lambdaScope.Accessor.Type, context.EntityModel); - MemberBinding[] propertyAssignments = propertySelectors.Select(selector => CreatePropertyAssignment(selector, lambdaScope, context)) - .Cast().ToArray(); + Dictionary.ValueCollection propertySelectors = + ToPropertySelectors(fieldSelectors, resourceType, context.LambdaScope.Accessor.Type, context.EntityModel); - NewExpression createInstance = _resourceFactory.CreateNewExpression(lambdaScope.Accessor.Type); + MemberBinding[] propertyAssignments = propertySelectors.Select(selector => CreatePropertyAssignment(selector, context)).Cast().ToArray(); + NewExpression createInstance = _resourceFactory.CreateNewExpression(context.LambdaScope.Accessor.Type); return Expression.MemberInit(createInstance, propertyAssignments); } - private static ICollection ToPropertySelectors(FieldSelectors fieldSelectors, ResourceType resourceType, Type elementType, - IReadOnlyModel entityModel) + private static Dictionary.ValueCollection ToPropertySelectors(FieldSelectors fieldSelectors, ResourceType resourceType, + Type elementType, IReadOnlyModel entityModel) { var propertySelectors = new Dictionary(); @@ -181,35 +191,40 @@ private static void IncludeEagerLoads(ResourceType resourceType, Dictionary argumentQueue, Func 0) { Expression nextArgument = argumentQueue.Dequeue(); tempExpression = applyOperator(tempExpression, nextArgument); diff --git a/src/JsonApiDotNetCore/Queries/SparseFieldSetCache.cs b/src/JsonApiDotNetCore/Queries/SparseFieldSetCache.cs index d812dc121b..0df2d5af75 100644 --- a/src/JsonApiDotNetCore/Queries/SparseFieldSetCache.cs +++ b/src/JsonApiDotNetCore/Queries/SparseFieldSetCache.cs @@ -13,20 +13,20 @@ public sealed class SparseFieldSetCache : ISparseFieldSetCache private static readonly ConcurrentDictionary ViewableFieldSetCache = new(); private readonly IResourceDefinitionAccessor _resourceDefinitionAccessor; - private readonly Lazy>> _lazySourceTable; - private readonly IDictionary> _visitedTable; + private readonly Lazy>> _lazySourceTable; + private readonly Dictionary> _visitedTable = []; public SparseFieldSetCache(IEnumerable constraintProviders, IResourceDefinitionAccessor resourceDefinitionAccessor) { - ArgumentGuard.NotNull(constraintProviders); - ArgumentGuard.NotNull(resourceDefinitionAccessor); + ArgumentNullException.ThrowIfNull(constraintProviders); + ArgumentNullException.ThrowIfNull(resourceDefinitionAccessor); _resourceDefinitionAccessor = resourceDefinitionAccessor; - _lazySourceTable = new Lazy>>(() => BuildSourceTable(constraintProviders)); - _visitedTable = new Dictionary>(); + _lazySourceTable = new Lazy>>(() => BuildSourceTable(constraintProviders)); } - private static IDictionary> BuildSourceTable(IEnumerable constraintProviders) + private static Dictionary> BuildSourceTable( + IEnumerable constraintProviders) { // @formatter:wrap_chained_method_calls chop_always // @formatter:wrap_before_first_method_call true @@ -47,15 +47,16 @@ private static IDictionary> foreach ((ResourceType resourceType, SparseFieldSetExpression sparseFieldSet) in sparseFieldTables) { - if (!mergedTable.ContainsKey(resourceType)) + if (!mergedTable.TryGetValue(resourceType, out ImmutableHashSet.Builder? builder)) { - mergedTable[resourceType] = ImmutableHashSet.CreateBuilder(); + builder = ImmutableHashSet.CreateBuilder(); + mergedTable[resourceType] = builder; } - AddSparseFieldsToSet(sparseFieldSet.Fields, mergedTable[resourceType]); + AddSparseFieldsToSet(sparseFieldSet.Fields, builder); } - return mergedTable.ToDictionary(pair => pair.Key, pair => (IImmutableSet)pair.Value.ToImmutable()); + return mergedTable.ToDictionary(pair => pair.Key, pair => pair.Value.ToImmutable()); } private static void AddSparseFieldsToSet(IImmutableSet sparseFieldsToAdd, @@ -70,30 +71,28 @@ private static void AddSparseFieldsToSet(IImmutableSet s /// public IImmutableSet GetSparseFieldSetForQuery(ResourceType resourceType) { - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(resourceType); - if (!_visitedTable.ContainsKey(resourceType)) + if (!_visitedTable.TryGetValue(resourceType, out IImmutableSet? outputFields)) { - SparseFieldSetExpression? inputExpression = _lazySourceTable.Value.TryGetValue(resourceType, out IImmutableSet? inputFields) - ? new SparseFieldSetExpression(inputFields) - : null; + SparseFieldSetExpression? inputExpression = + _lazySourceTable.Value.TryGetValue(resourceType, out ImmutableHashSet? inputFields) + ? new SparseFieldSetExpression(inputFields) + : null; SparseFieldSetExpression? outputExpression = _resourceDefinitionAccessor.OnApplySparseFieldSet(resourceType, inputExpression); - - IImmutableSet outputFields = outputExpression == null - ? ImmutableHashSet.Empty - : outputExpression.Fields; + outputFields = outputExpression == null ? ImmutableHashSet.Empty : outputExpression.Fields; _visitedTable[resourceType] = outputFields; } - return _visitedTable[resourceType]; + return outputFields; } /// public IImmutableSet GetIdAttributeSetForRelationshipQuery(ResourceType resourceType) { - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(resourceType); AttrAttribute idAttribute = resourceType.GetAttributeByPropertyName(nameof(Identifiable.Id)); var inputExpression = new SparseFieldSetExpression(ImmutableHashSet.Create(idAttribute)); @@ -112,31 +111,32 @@ public IImmutableSet GetIdAttributeSetForRelationshipQuery(Resour /// public IImmutableSet GetSparseFieldSetForSerializer(ResourceType resourceType) { - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(resourceType); - if (!_visitedTable.ContainsKey(resourceType)) + if (!_visitedTable.TryGetValue(resourceType, out IImmutableSet? outputFields)) { - SparseFieldSetExpression inputExpression = _lazySourceTable.Value.TryGetValue(resourceType, out IImmutableSet? inputFields) - ? new SparseFieldSetExpression(inputFields) - : GetCachedViewableFieldSet(resourceType); + SparseFieldSetExpression inputExpression = + _lazySourceTable.Value.TryGetValue(resourceType, out ImmutableHashSet? inputFields) + ? new SparseFieldSetExpression(inputFields) + : GetCachedViewableFieldSet(resourceType); SparseFieldSetExpression? outputExpression = _resourceDefinitionAccessor.OnApplySparseFieldSet(resourceType, inputExpression); - IImmutableSet outputFields = outputExpression == null + outputFields = outputExpression == null ? GetCachedViewableFieldSet(resourceType).Fields : inputExpression.Fields.Intersect(outputExpression.Fields); _visitedTable[resourceType] = outputFields; } - return _visitedTable[resourceType]; + return outputFields; } private static SparseFieldSetExpression GetCachedViewableFieldSet(ResourceType resourceType) { if (!ViewableFieldSetCache.TryGetValue(resourceType, out SparseFieldSetExpression? fieldSet)) { - IImmutableSet viewableFields = GetViewableFields(resourceType); + ImmutableHashSet viewableFields = GetViewableFields(resourceType); fieldSet = new SparseFieldSetExpression(viewableFields); ViewableFieldSetCache[resourceType] = fieldSet; } @@ -144,16 +144,9 @@ private static SparseFieldSetExpression GetCachedViewableFieldSet(ResourceType r return fieldSet; } - private static IImmutableSet GetViewableFields(ResourceType resourceType) + private static ImmutableHashSet GetViewableFields(ResourceType resourceType) { - ImmutableHashSet.Builder fieldSetBuilder = ImmutableHashSet.CreateBuilder(); - - foreach (ResourceFieldAttribute field in resourceType.Fields.Where(nextField => !nextField.IsViewBlocked())) - { - fieldSetBuilder.Add(field); - } - - return fieldSetBuilder.ToImmutable(); + return resourceType.Fields.Where(nextField => !nextField.IsViewBlocked()).ToImmutableHashSet(); } public void Reset() diff --git a/src/JsonApiDotNetCore/Queries/SystemExpressionBuilder.cs b/src/JsonApiDotNetCore/Queries/SystemExpressionBuilder.cs index f625ee9b4f..72a30a060a 100644 --- a/src/JsonApiDotNetCore/Queries/SystemExpressionBuilder.cs +++ b/src/JsonApiDotNetCore/Queries/SystemExpressionBuilder.cs @@ -20,7 +20,7 @@ internal static class SystemExpressionBuilder public static Expression CloseOver(object value) { - ArgumentGuard.NotNull(value); + ArgumentNullException.ThrowIfNull(value); MethodInfo closeOverClosedMethod = CloseOverOpenMethod.MakeGenericMethod(value.GetType()); return (Expression)closeOverClosedMethod.Invoke(null, [value])!; diff --git a/src/JsonApiDotNetCore/QueryStrings/FieldChains/FieldChainFormatException.cs b/src/JsonApiDotNetCore/QueryStrings/FieldChains/FieldChainFormatException.cs index d4e0d35d55..f7a81aa443 100644 --- a/src/JsonApiDotNetCore/QueryStrings/FieldChains/FieldChainFormatException.cs +++ b/src/JsonApiDotNetCore/QueryStrings/FieldChains/FieldChainFormatException.cs @@ -3,7 +3,8 @@ namespace JsonApiDotNetCore.QueryStrings.FieldChains; /// /// The exception that is thrown when the format of a dot-separated resource field chain is invalid. /// -internal sealed class FieldChainFormatException(int position, string message) : FormatException(message) +internal sealed class FieldChainFormatException(int position, string message) + : FormatException(message) { /// /// Gets the zero-based error position in the field chain, or at its end. diff --git a/src/JsonApiDotNetCore/QueryStrings/FieldChains/FieldChainParser.cs b/src/JsonApiDotNetCore/QueryStrings/FieldChains/FieldChainParser.cs index e6dac0b258..0bbea6b63f 100644 --- a/src/JsonApiDotNetCore/QueryStrings/FieldChains/FieldChainParser.cs +++ b/src/JsonApiDotNetCore/QueryStrings/FieldChains/FieldChainParser.cs @@ -7,9 +7,9 @@ internal sealed class FieldChainParser { public IEnumerable Parse(string source) { - ArgumentGuard.NotNull(source); + ArgumentNullException.ThrowIfNull(source); - if (source != string.Empty) + if (source.Length > 0) { var fields = new List(source.Split('.')); int position = 0; diff --git a/src/JsonApiDotNetCore/QueryStrings/FieldChains/FieldChainPattern.cs b/src/JsonApiDotNetCore/QueryStrings/FieldChains/FieldChainPattern.cs index fb63c6a03d..e3c15ebdbe 100644 --- a/src/JsonApiDotNetCore/QueryStrings/FieldChains/FieldChainPattern.cs +++ b/src/JsonApiDotNetCore/QueryStrings/FieldChains/FieldChainPattern.cs @@ -144,8 +144,8 @@ public static FieldChainPattern Parse(string pattern) public PatternMatchResult Match(string fieldChain, ResourceType resourceType, FieldChainPatternMatchOptions options = FieldChainPatternMatchOptions.None, ILoggerFactory? loggerFactory = null) { - ArgumentGuard.NotNull(fieldChain); - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(fieldChain); + ArgumentNullException.ThrowIfNull(resourceType); ILogger logger = loggerFactory == null ? NullLogger.Instance : loggerFactory.CreateLogger(); var matcher = new PatternMatcher(this, options, logger); diff --git a/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchError.cs b/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchError.cs index 8fe555b2f3..3707151560 100644 --- a/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchError.cs +++ b/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchError.cs @@ -37,7 +37,7 @@ public static MatchError CreateForBrokenFieldChain(FieldChainFormatException exc public static MatchError CreateForUnknownField(int position, ResourceType? resourceType, string publicName, bool allowDerivedTypes) { - bool hasDerivedTypes = allowDerivedTypes && resourceType != null && resourceType.DirectlyDerivedTypes.Any(); + bool hasDerivedTypes = allowDerivedTypes && resourceType is { DirectlyDerivedTypes.Count: > 0 }; var builder = new MessageBuilder(); diff --git a/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchState.cs b/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchState.cs index a0aa58e377..678850e4c4 100644 --- a/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchState.cs +++ b/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchState.cs @@ -53,9 +53,9 @@ private MatchState(FieldChainPattern? pattern, ResourceType? resourceType, IImmu public static MatchState Create(FieldChainPattern pattern, string fieldChainText, ResourceType resourceType) { - ArgumentGuard.NotNull(pattern); - ArgumentGuard.NotNull(fieldChainText); - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(pattern); + ArgumentNullException.ThrowIfNull(fieldChainText); + ArgumentNullException.ThrowIfNull(resourceType); try { @@ -77,7 +77,7 @@ public static MatchState Create(FieldChainPattern pattern, string fieldChainText /// public MatchState SuccessMoveForwardOneField(ResourceFieldAttribute matchedValue) { - ArgumentGuard.NotNull(matchedValue); + ArgumentNullException.ThrowIfNull(matchedValue); AssertIsSuccess(this); IImmutableList fieldsMatched = FieldsMatched.Add(matchedValue); @@ -253,7 +253,7 @@ public IReadOnlyList GetAllFieldsMatched() fields.AddRange(matches); } - return fields; + return fields.AsReadOnly(); } private static void AssertIsSuccess(MatchState state) diff --git a/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchTraceScope.cs b/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchTraceScope.cs index 653c029e46..5f3dd5f713 100644 --- a/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchTraceScope.cs +++ b/src/JsonApiDotNetCore/QueryStrings/FieldChains/MatchTraceScope.cs @@ -1,13 +1,11 @@ using Microsoft.Extensions.Logging; -#pragma warning disable CA2254 // Template should be a static expression - namespace JsonApiDotNetCore.QueryStrings.FieldChains; /// /// Logs the pattern matching steps at level. /// -internal sealed class MatchTraceScope : IDisposable +internal sealed partial class MatchTraceScope : IDisposable { private readonly FieldChainPattern? _pattern; private readonly bool _isEnabled; @@ -25,32 +23,33 @@ private MatchTraceScope(FieldChainPattern? pattern, bool isEnabled, ILogger logg public static MatchTraceScope CreateRoot(MatchState startState, ILogger logger) { - ArgumentGuard.NotNull(startState); - ArgumentGuard.NotNull(logger); + ArgumentNullException.ThrowIfNull(startState); + ArgumentNullException.ThrowIfNull(logger); bool isEnabled = logger.IsEnabled(LogLevel.Trace); + var scope = new MatchTraceScope(startState.Pattern, isEnabled, logger, 0); if (isEnabled) { string fieldsRemaining = FormatFieldsRemaining(startState); - string message = $"Start matching pattern '{startState.Pattern}' against the complete chain '{fieldsRemaining}'"; - logger.LogTrace(message); + scope.LogMatchFirst(startState.Pattern, fieldsRemaining); } - return new MatchTraceScope(startState.Pattern, isEnabled, logger, 0); + return scope; } public MatchTraceScope CreateChild(MatchState startState) { - ArgumentGuard.NotNull(startState); + ArgumentNullException.ThrowIfNull(startState); int indentDepth = _indentDepth + 1; FieldChainPattern? patternSegment = startState.Pattern?.WithoutNext(); if (_isEnabled) { + string indent = GetIndentText(); string fieldsRemaining = FormatFieldsRemaining(startState); - LogMessage($"Start matching '{patternSegment}' against the remaining chain '{fieldsRemaining}'"); + LogMatchNext(indent, patternSegment, fieldsRemaining); } return new MatchTraceScope(patternSegment, _isEnabled, _logger, indentDepth); @@ -58,18 +57,20 @@ public MatchTraceScope CreateChild(MatchState startState) public void LogMatchResult(MatchState resultState) { - ArgumentGuard.NotNull(resultState); + ArgumentNullException.ThrowIfNull(resultState); if (_isEnabled) { + string indent = GetIndentText(); + if (resultState.Error == null) { string fieldsMatched = FormatFieldsMatched(resultState); - LogMessage($"Match '{_pattern}' against '{fieldsMatched}': Success"); + LogMatchSuccess(indent, _pattern, fieldsMatched); } else { - List chain = [..resultState.FieldsMatched.Select(attribute => attribute.PublicName)]; + List chain = [.. resultState.FieldsMatched.Select(attribute => attribute.PublicName)]; if (resultState.FieldsRemaining != null) { @@ -77,25 +78,26 @@ public void LogMatchResult(MatchState resultState) } string chainText = string.Join('.', chain); - LogMessage($"Match '{_pattern}' against '{chainText}': Failed"); + LogMatchFailed(indent, _pattern, chainText); } } } public void LogBacktrackTo(MatchState backtrackState) { - ArgumentGuard.NotNull(backtrackState); + ArgumentNullException.ThrowIfNull(backtrackState); if (_isEnabled) { + string indent = GetIndentText(); string fieldsMatched = FormatFieldsMatched(backtrackState); - LogMessage($"Backtracking to successful match against '{fieldsMatched}'"); + LogBacktrack(indent, fieldsMatched); } } public void SetResult(MatchState endState) { - ArgumentGuard.NotNull(endState); + ArgumentNullException.ThrowIfNull(endState); _endState = endState; } @@ -109,7 +111,16 @@ public void Dispose() if (_isEnabled) { - LogMessage(_endState.Error == null ? "Matching completed with success" : "Matching completed with failure"); + string indent = GetIndentText(); + + if (_endState.Error == null) + { + LogCompletionSuccess(indent); + } + else + { + LogCompletionFailure(indent); + } } } @@ -123,9 +134,30 @@ private static string FormatFieldsMatched(MatchState state) return string.Join('.', state.FieldsMatched); } - private void LogMessage(string message) + private string GetIndentText() { - string indent = new(' ', _indentDepth * 2); - _logger.LogTrace($"{indent}{message}"); + return new string(' ', _indentDepth * 2); } + + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, Message = "Start matching pattern '{Pattern}' against the complete chain '{Chain}'.")] + private partial void LogMatchFirst(FieldChainPattern? pattern, string chain); + + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, + Message = "{Indent}Start matching pattern '{Pattern}' against the remaining chain '{Chain}'.")] + private partial void LogMatchNext(string indent, FieldChainPattern? pattern, string chain); + + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, Message = "{Indent}Match pattern '{Pattern}' against the chain '{Chain}': Success.")] + private partial void LogMatchSuccess(string indent, FieldChainPattern? pattern, string chain); + + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, Message = "{Indent}Match pattern '{Pattern}' against the chain '{Chain}': Failed.")] + private partial void LogMatchFailed(string indent, FieldChainPattern? pattern, string chain); + + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, Message = "{Indent}Backtracking to successful match against '{Chain}'.")] + private partial void LogBacktrack(string indent, string chain); + + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, Message = "{Indent}Matching completed with success.")] + private partial void LogCompletionSuccess(string indent); + + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, Message = "{Indent}Matching completed with failure.")] + private partial void LogCompletionFailure(string indent); } diff --git a/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternDescriptionFormatter.cs b/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternDescriptionFormatter.cs index 841dbb2050..bdd29e3200 100644 --- a/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternDescriptionFormatter.cs +++ b/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternDescriptionFormatter.cs @@ -11,7 +11,7 @@ internal sealed class PatternDescriptionFormatter public PatternDescriptionFormatter(FieldChainPattern pattern) { - ArgumentGuard.NotNull(pattern); + ArgumentNullException.ThrowIfNull(pattern); _pattern = pattern; } diff --git a/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternFormatException.cs b/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternFormatException.cs index 04a73f7f72..3a607c435f 100644 --- a/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternFormatException.cs +++ b/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternFormatException.cs @@ -6,7 +6,8 @@ namespace JsonApiDotNetCore.QueryStrings.FieldChains; /// The exception that is thrown when the format of a is invalid. /// [PublicAPI] -public sealed class PatternFormatException(string pattern, int position, string message) : FormatException(message) +public sealed class PatternFormatException(string pattern, int position, string message) + : FormatException(message) { /// /// Gets the text of the invalid pattern. diff --git a/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternMatchResult.cs b/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternMatchResult.cs index f32ff953f4..6b9a1d1075 100644 --- a/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternMatchResult.cs +++ b/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternMatchResult.cs @@ -49,14 +49,14 @@ private PatternMatchResult(bool isSuccess, IReadOnlyList internal static PatternMatchResult CreateForSuccess(IReadOnlyList fieldChain) { - ArgumentGuard.NotNull(fieldChain); + ArgumentNullException.ThrowIfNull(fieldChain); return new PatternMatchResult(true, fieldChain, string.Empty, -1, false); } internal static PatternMatchResult CreateForFailure(MatchError error) { - ArgumentGuard.NotNull(error); + ArgumentNullException.ThrowIfNull(error); return new PatternMatchResult(false, Array.Empty(), error.Message, error.Position, error.IsFieldChainError); } diff --git a/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternMatcher.cs b/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternMatcher.cs index 049aac2b94..9a86542533 100644 --- a/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternMatcher.cs +++ b/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternMatcher.cs @@ -15,8 +15,8 @@ internal sealed class PatternMatcher public PatternMatcher(FieldChainPattern pattern, FieldChainPatternMatchOptions options, ILogger logger) { - ArgumentGuard.NotNull(pattern); - ArgumentGuard.NotNull(logger); + ArgumentNullException.ThrowIfNull(pattern); + ArgumentNullException.ThrowIfNull(logger); _pattern = pattern; _logger = logger; @@ -25,8 +25,8 @@ public PatternMatcher(FieldChainPattern pattern, FieldChainPatternMatchOptions o public PatternMatchResult Match(string fieldChain, ResourceType resourceType) { - ArgumentGuard.NotNull(fieldChain); - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(fieldChain); + ArgumentNullException.ThrowIfNull(resourceType); var startState = MatchState.Create(_pattern, fieldChain, resourceType); @@ -157,7 +157,7 @@ private MatchState MatchField(MatchState state) HashSet fields = LookupFields(state.ResourceType, publicName); - if (!fields.Any()) + if (fields.Count == 0) { return state.FailureForUnknownField(publicName, _allowDerivedTypes); } diff --git a/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternParser.cs b/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternParser.cs index cc0fa0a69e..c6e05fdd4f 100644 --- a/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternParser.cs +++ b/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternParser.cs @@ -41,7 +41,7 @@ internal sealed class PatternParser public FieldChainPattern Parse(string source) { - ArgumentGuard.NotNull(source); + ArgumentNullException.ThrowIfNull(source); _source = source; EnqueueTokens(); diff --git a/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternTextFormatter.cs b/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternTextFormatter.cs index 6e12ad8481..2fec95b900 100644 --- a/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternTextFormatter.cs +++ b/src/JsonApiDotNetCore/QueryStrings/FieldChains/PatternTextFormatter.cs @@ -11,7 +11,7 @@ internal sealed class PatternTextFormatter public PatternTextFormatter(FieldChainPattern pattern) { - ArgumentGuard.NotNull(pattern); + ArgumentNullException.ThrowIfNull(pattern); _pattern = pattern; } diff --git a/src/JsonApiDotNetCore/QueryStrings/FilterQueryStringParameterReader.cs b/src/JsonApiDotNetCore/QueryStrings/FilterQueryStringParameterReader.cs index 6ebdd4fd29..6b85273ddb 100644 --- a/src/JsonApiDotNetCore/QueryStrings/FilterQueryStringParameterReader.cs +++ b/src/JsonApiDotNetCore/QueryStrings/FilterQueryStringParameterReader.cs @@ -30,9 +30,9 @@ public FilterQueryStringParameterReader(IQueryStringParameterScopeParser scopePa IResourceGraph resourceGraph, IJsonApiOptions options) : base(request, resourceGraph) { - ArgumentGuard.NotNull(scopeParser); - ArgumentGuard.NotNull(filterParser); - ArgumentGuard.NotNull(options); + ArgumentNullException.ThrowIfNull(scopeParser); + ArgumentNullException.ThrowIfNull(filterParser); + ArgumentNullException.ThrowIfNull(options); _options = options; _scopeParser = scopeParser; @@ -42,7 +42,7 @@ public FilterQueryStringParameterReader(IQueryStringParameterScopeParser scopePa /// public virtual bool IsEnabled(DisableQueryStringAttribute disableQueryStringAttribute) { - ArgumentGuard.NotNull(disableQueryStringAttribute); + ArgumentNullException.ThrowIfNull(disableQueryStringAttribute); return !IsAtomicOperationsRequest && !disableQueryStringAttribute.ContainsParameter(JsonApiQueryStringParameters.Filter); } @@ -50,7 +50,7 @@ public virtual bool IsEnabled(DisableQueryStringAttribute disableQueryStringAttr /// public virtual bool CanRead(string parameterName) { - ArgumentGuard.NotNullNorEmpty(parameterName); + ArgumentException.ThrowIfNullOrEmpty(parameterName); bool isNested = parameterName.StartsWith("filter[", StringComparison.Ordinal) && parameterName.EndsWith(']'); return parameterName == "filter" || isNested; @@ -140,24 +140,25 @@ private void StoreFilterInScope(FilterExpression filter, ResourceFieldChainExpre } else { - if (!_filtersPerScope.ContainsKey(scope)) + if (!_filtersPerScope.TryGetValue(scope, out ImmutableArray.Builder? builder)) { - _filtersPerScope[scope] = ImmutableArray.CreateBuilder(); + builder = ImmutableArray.CreateBuilder(); + _filtersPerScope[scope] = builder; } - _filtersPerScope[scope].Add(filter); + builder.Add(filter); } } /// public virtual IReadOnlyCollection GetConstraints() { - return EnumerateFiltersInScopes().ToArray(); + return EnumerateFiltersInScopes().ToArray().AsReadOnly(); } private IEnumerable EnumerateFiltersInScopes() { - if (_filtersInGlobalScope.Any()) + if (_filtersInGlobalScope.Count > 0) { FilterExpression filter = MergeFilters(_filtersInGlobalScope.ToImmutable()); yield return new ExpressionInScope(null, filter); @@ -172,6 +173,6 @@ private IEnumerable EnumerateFiltersInScopes() private static FilterExpression MergeFilters(IImmutableList filters) { - return filters.Count > 1 ? new LogicalExpression(LogicalOperator.Or, filters) : filters.First(); + return filters.Count > 1 ? new LogicalExpression(LogicalOperator.Or, filters) : filters[0]; } } diff --git a/src/JsonApiDotNetCore/QueryStrings/IncludeQueryStringParameterReader.cs b/src/JsonApiDotNetCore/QueryStrings/IncludeQueryStringParameterReader.cs index ba0f889809..55ef25779f 100644 --- a/src/JsonApiDotNetCore/QueryStrings/IncludeQueryStringParameterReader.cs +++ b/src/JsonApiDotNetCore/QueryStrings/IncludeQueryStringParameterReader.cs @@ -23,7 +23,7 @@ public class IncludeQueryStringParameterReader : QueryStringParameterReader, IIn public IncludeQueryStringParameterReader(IIncludeParser includeParser, IJsonApiRequest request, IResourceGraph resourceGraph) : base(request, resourceGraph) { - ArgumentGuard.NotNull(includeParser); + ArgumentNullException.ThrowIfNull(includeParser); _includeParser = includeParser; } @@ -31,7 +31,7 @@ public IncludeQueryStringParameterReader(IIncludeParser includeParser, IJsonApiR /// public virtual bool IsEnabled(DisableQueryStringAttribute disableQueryStringAttribute) { - ArgumentGuard.NotNull(disableQueryStringAttribute); + ArgumentNullException.ThrowIfNull(disableQueryStringAttribute); return !IsAtomicOperationsRequest && !disableQueryStringAttribute.ContainsParameter(JsonApiQueryStringParameters.Include); } @@ -39,6 +39,8 @@ public virtual bool IsEnabled(DisableQueryStringAttribute disableQueryStringAttr /// public virtual bool CanRead(string parameterName) { + ArgumentException.ThrowIfNullOrEmpty(parameterName); + return parameterName == "include"; } diff --git a/src/JsonApiDotNetCore/QueryStrings/LegacyFilterNotationConverter.cs b/src/JsonApiDotNetCore/QueryStrings/LegacyFilterNotationConverter.cs index 0480158133..eff147e3d4 100644 --- a/src/JsonApiDotNetCore/QueryStrings/LegacyFilterNotationConverter.cs +++ b/src/JsonApiDotNetCore/QueryStrings/LegacyFilterNotationConverter.cs @@ -22,7 +22,7 @@ public sealed class LegacyFilterNotationConverter public IEnumerable ExtractConditions(string parameterValue) { - ArgumentGuard.NotNullNorEmpty(parameterValue); + ArgumentException.ThrowIfNullOrEmpty(parameterValue); if (parameterValue.StartsWith(ParameterValuePrefix.Expression, StringComparison.Ordinal) || parameterValue.StartsWith(ParameterValuePrefix.In, StringComparison.Ordinal) || @@ -41,8 +41,8 @@ public IEnumerable ExtractConditions(string parameterValue) public (string parameterName, string parameterValue) Convert(string parameterName, string parameterValue) { - ArgumentGuard.NotNullNorEmpty(parameterName); - ArgumentGuard.NotNullNorEmpty(parameterValue); + ArgumentException.ThrowIfNullOrEmpty(parameterName); + ArgumentException.ThrowIfNullOrEmpty(parameterValue); if (parameterValue.StartsWith(ParameterValuePrefix.Expression, StringComparison.Ordinal)) { diff --git a/src/JsonApiDotNetCore/QueryStrings/PaginationQueryStringParameterReader.cs b/src/JsonApiDotNetCore/QueryStrings/PaginationQueryStringParameterReader.cs index e46e59ce18..353204eee2 100644 --- a/src/JsonApiDotNetCore/QueryStrings/PaginationQueryStringParameterReader.cs +++ b/src/JsonApiDotNetCore/QueryStrings/PaginationQueryStringParameterReader.cs @@ -1,4 +1,5 @@ using System.Collections.Immutable; +using System.Collections.ObjectModel; using JetBrains.Annotations; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Controllers.Annotations; @@ -30,8 +31,8 @@ public PaginationQueryStringParameterReader(IPaginationParser paginationParser, IJsonApiOptions options) : base(request, resourceGraph) { - ArgumentGuard.NotNull(paginationParser); - ArgumentGuard.NotNull(options); + ArgumentNullException.ThrowIfNull(paginationParser); + ArgumentNullException.ThrowIfNull(options); _options = options; _paginationParser = paginationParser; @@ -40,7 +41,7 @@ public PaginationQueryStringParameterReader(IPaginationParser paginationParser, /// public virtual bool IsEnabled(DisableQueryStringAttribute disableQueryStringAttribute) { - ArgumentGuard.NotNull(disableQueryStringAttribute); + ArgumentNullException.ThrowIfNull(disableQueryStringAttribute); return !IsAtomicOperationsRequest && !disableQueryStringAttribute.ContainsParameter(JsonApiQueryStringParameters.Page); } @@ -48,6 +49,8 @@ public virtual bool IsEnabled(DisableQueryStringAttribute disableQueryStringAttr /// public virtual bool CanRead(string parameterName) { + ArgumentException.ThrowIfNullOrEmpty(parameterName); + return parameterName is PageSizeParameterName or PageNumberParameterName; } @@ -92,6 +95,8 @@ private PaginationQueryStringValueExpression GetPageConstraint(string parameterV protected virtual void ValidatePageSize(PaginationQueryStringValueExpression constraint) { + ArgumentNullException.ThrowIfNull(constraint); + foreach (PaginationElementQueryStringValueExpression element in constraint.Elements) { if (_options.MaximumPageSize != null) @@ -116,6 +121,8 @@ protected virtual void ValidatePageSize(PaginationQueryStringValueExpression con protected virtual void ValidatePageNumber(PaginationQueryStringValueExpression constraint) { + ArgumentNullException.ThrowIfNull(constraint); + foreach (PaginationElementQueryStringValueExpression element in constraint.Elements) { if (_options.MaximumPageNumber != null) @@ -194,9 +201,9 @@ private void ApplyOptionsInEntry(MutablePaginationEntry entry, IJsonApiOptions o entry.PageNumber ??= PageNumber.ValueOne; } - public IReadOnlyCollection GetExpressionsInScope() + public ReadOnlyCollection GetExpressionsInScope() { - return EnumerateExpressionsInScope().ToArray(); + return EnumerateExpressionsInScope().ToArray().AsReadOnly(); } private IEnumerable EnumerateExpressionsInScope() diff --git a/src/JsonApiDotNetCore/QueryStrings/QueryStringParameterReader.cs b/src/JsonApiDotNetCore/QueryStrings/QueryStringParameterReader.cs index d3f5277881..1b59eed083 100644 --- a/src/JsonApiDotNetCore/QueryStrings/QueryStringParameterReader.cs +++ b/src/JsonApiDotNetCore/QueryStrings/QueryStringParameterReader.cs @@ -16,8 +16,8 @@ public abstract class QueryStringParameterReader protected QueryStringParameterReader(IJsonApiRequest request, IResourceGraph resourceGraph) { - ArgumentGuard.NotNull(request); - ArgumentGuard.NotNull(resourceGraph); + ArgumentNullException.ThrowIfNull(request); + ArgumentNullException.ThrowIfNull(resourceGraph); _resourceGraph = resourceGraph; _isCollectionRequest = request.IsCollection; diff --git a/src/JsonApiDotNetCore/QueryStrings/QueryStringReader.cs b/src/JsonApiDotNetCore/QueryStrings/QueryStringReader.cs index e3c944a045..89337708e7 100644 --- a/src/JsonApiDotNetCore/QueryStrings/QueryStringReader.cs +++ b/src/JsonApiDotNetCore/QueryStrings/QueryStringReader.cs @@ -8,24 +8,24 @@ namespace JsonApiDotNetCore.QueryStrings; /// -public sealed class QueryStringReader : IQueryStringReader +public sealed partial class QueryStringReader : IQueryStringReader { private readonly IJsonApiOptions _options; private readonly IRequestQueryStringAccessor _queryStringAccessor; - private readonly IEnumerable _parameterReaders; + private readonly IQueryStringParameterReader[] _parameterReaders; private readonly ILogger _logger; public QueryStringReader(IJsonApiOptions options, IRequestQueryStringAccessor queryStringAccessor, IEnumerable parameterReaders, ILoggerFactory loggerFactory) { - ArgumentGuard.NotNull(loggerFactory); - ArgumentGuard.NotNull(options); - ArgumentGuard.NotNull(queryStringAccessor); - ArgumentGuard.NotNull(parameterReaders); + ArgumentNullException.ThrowIfNull(loggerFactory); + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(queryStringAccessor); + ArgumentNullException.ThrowIfNull(parameterReaders); _options = options; _queryStringAccessor = queryStringAccessor; - _parameterReaders = parameterReaders; + _parameterReaders = parameterReaders as IQueryStringParameterReader[] ?? parameterReaders.ToArray(); _logger = loggerFactory.CreateLogger(); } @@ -47,7 +47,7 @@ public void ReadAll(DisableQueryStringAttribute? disableQueryStringAttribute) if (reader != null) { - _logger.LogDebug($"Query string parameter '{parameterName}' with value '{parameterValue}' was accepted by {reader.GetType().Name}."); + LogParameterAccepted(parameterName, parameterValue, reader.GetType().Name); if (!reader.AllowEmptyValue && string.IsNullOrEmpty(parameterValue)) { @@ -63,7 +63,7 @@ public void ReadAll(DisableQueryStringAttribute? disableQueryStringAttribute) } reader.Read(parameterName, parameterValue); - _logger.LogDebug($"Query string parameter '{parameterName}' was successfully read."); + LogParameterRead(parameterName); } else if (!_options.AllowUnknownQueryStringParameters) { @@ -73,4 +73,10 @@ public void ReadAll(DisableQueryStringAttribute? disableQueryStringAttribute) } } } + + [LoggerMessage(Level = LogLevel.Debug, Message = "Query string parameter '{ParameterName}' with value '{ParameterValue}' was accepted by {ReaderType}.")] + private partial void LogParameterAccepted(string parameterName, StringValues parameterValue, string readerType); + + [LoggerMessage(Level = LogLevel.Debug, Message = "Query string parameter '{ParameterName}' was successfully read.")] + private partial void LogParameterRead(string parameterName); } diff --git a/src/JsonApiDotNetCore/QueryStrings/RequestQueryStringAccessor.cs b/src/JsonApiDotNetCore/QueryStrings/RequestQueryStringAccessor.cs index 00c0bfb69f..92b9a0a60a 100644 --- a/src/JsonApiDotNetCore/QueryStrings/RequestQueryStringAccessor.cs +++ b/src/JsonApiDotNetCore/QueryStrings/RequestQueryStringAccessor.cs @@ -22,7 +22,7 @@ public IQueryCollection Query public RequestQueryStringAccessor(IHttpContextAccessor httpContextAccessor) { - ArgumentGuard.NotNull(httpContextAccessor); + ArgumentNullException.ThrowIfNull(httpContextAccessor); _httpContextAccessor = httpContextAccessor; } diff --git a/src/JsonApiDotNetCore/QueryStrings/ResourceDefinitionQueryableParameterReader.cs b/src/JsonApiDotNetCore/QueryStrings/ResourceDefinitionQueryableParameterReader.cs index 3d844e4b48..fb52e5775d 100644 --- a/src/JsonApiDotNetCore/QueryStrings/ResourceDefinitionQueryableParameterReader.cs +++ b/src/JsonApiDotNetCore/QueryStrings/ResourceDefinitionQueryableParameterReader.cs @@ -21,8 +21,8 @@ public class ResourceDefinitionQueryableParameterReader : IResourceDefinitionQue public ResourceDefinitionQueryableParameterReader(IJsonApiRequest request, IResourceDefinitionAccessor resourceDefinitionAccessor) { - ArgumentGuard.NotNull(request); - ArgumentGuard.NotNull(resourceDefinitionAccessor); + ArgumentNullException.ThrowIfNull(request); + ArgumentNullException.ThrowIfNull(resourceDefinitionAccessor); _request = request; _resourceDefinitionAccessor = resourceDefinitionAccessor; @@ -37,6 +37,8 @@ public virtual bool IsEnabled(DisableQueryStringAttribute disableQueryStringAttr /// public virtual bool CanRead(string parameterName) { + ArgumentException.ThrowIfNullOrEmpty(parameterName); + if (_request.Kind == EndpointKind.AtomicOperations) { return false; @@ -71,6 +73,6 @@ public virtual void Read(string parameterName, StringValues parameterValue) /// public virtual IReadOnlyCollection GetConstraints() { - return _constraints; + return _constraints.AsReadOnly(); } } diff --git a/src/JsonApiDotNetCore/QueryStrings/SortQueryStringParameterReader.cs b/src/JsonApiDotNetCore/QueryStrings/SortQueryStringParameterReader.cs index d1ff5fface..203ee70235 100644 --- a/src/JsonApiDotNetCore/QueryStrings/SortQueryStringParameterReader.cs +++ b/src/JsonApiDotNetCore/QueryStrings/SortQueryStringParameterReader.cs @@ -25,8 +25,8 @@ public SortQueryStringParameterReader(IQueryStringParameterScopeParser scopePars IResourceGraph resourceGraph) : base(request, resourceGraph) { - ArgumentGuard.NotNull(scopeParser); - ArgumentGuard.NotNull(sortParser); + ArgumentNullException.ThrowIfNull(scopeParser); + ArgumentNullException.ThrowIfNull(sortParser); _scopeParser = scopeParser; _sortParser = sortParser; @@ -35,7 +35,7 @@ public SortQueryStringParameterReader(IQueryStringParameterScopeParser scopePars /// public virtual bool IsEnabled(DisableQueryStringAttribute disableQueryStringAttribute) { - ArgumentGuard.NotNull(disableQueryStringAttribute); + ArgumentNullException.ThrowIfNull(disableQueryStringAttribute); return !IsAtomicOperationsRequest && !disableQueryStringAttribute.ContainsParameter(JsonApiQueryStringParameters.Sort); } @@ -43,7 +43,7 @@ public virtual bool IsEnabled(DisableQueryStringAttribute disableQueryStringAttr /// public virtual bool CanRead(string parameterName) { - ArgumentGuard.NotNullNorEmpty(parameterName); + ArgumentException.ThrowIfNullOrEmpty(parameterName); bool isNested = parameterName.StartsWith("sort[", StringComparison.Ordinal) && parameterName.EndsWith(']'); return parameterName == "sort" || isNested; @@ -92,6 +92,6 @@ private SortExpression GetSort(string parameterValue, ResourceFieldChainExpressi /// public virtual IReadOnlyCollection GetConstraints() { - return _constraints; + return _constraints.AsReadOnly(); } } diff --git a/src/JsonApiDotNetCore/QueryStrings/SparseFieldSetQueryStringParameterReader.cs b/src/JsonApiDotNetCore/QueryStrings/SparseFieldSetQueryStringParameterReader.cs index c147285636..308fe44588 100644 --- a/src/JsonApiDotNetCore/QueryStrings/SparseFieldSetQueryStringParameterReader.cs +++ b/src/JsonApiDotNetCore/QueryStrings/SparseFieldSetQueryStringParameterReader.cs @@ -24,14 +24,14 @@ public class SparseFieldSetQueryStringParameterReader : QueryStringParameterRead ImmutableDictionary.CreateBuilder(); /// - bool IQueryStringParameterReader.AllowEmptyValue => true; + public bool AllowEmptyValue => true; public SparseFieldSetQueryStringParameterReader(ISparseFieldTypeParser scopeParser, ISparseFieldSetParser sparseFieldSetParser, IJsonApiRequest request, IResourceGraph resourceGraph) : base(request, resourceGraph) { - ArgumentGuard.NotNull(scopeParser); - ArgumentGuard.NotNull(sparseFieldSetParser); + ArgumentNullException.ThrowIfNull(scopeParser); + ArgumentNullException.ThrowIfNull(sparseFieldSetParser); _scopeParser = scopeParser; _sparseFieldSetParser = sparseFieldSetParser; @@ -40,7 +40,7 @@ public SparseFieldSetQueryStringParameterReader(ISparseFieldTypeParser scopePars /// public virtual bool IsEnabled(DisableQueryStringAttribute disableQueryStringAttribute) { - ArgumentGuard.NotNull(disableQueryStringAttribute); + ArgumentNullException.ThrowIfNull(disableQueryStringAttribute); return !IsAtomicOperationsRequest && !disableQueryStringAttribute.ContainsParameter(JsonApiQueryStringParameters.Fields); } @@ -48,7 +48,7 @@ public virtual bool IsEnabled(DisableQueryStringAttribute disableQueryStringAttr /// public virtual bool CanRead(string parameterName) { - ArgumentGuard.NotNullNorEmpty(parameterName); + ArgumentException.ThrowIfNullOrEmpty(parameterName); return parameterName.StartsWith("fields[", StringComparison.Ordinal) && parameterName.EndsWith(']'); } @@ -95,7 +95,7 @@ private SparseFieldSetExpression GetSparseFieldSet(string parameterValue, Resour /// public virtual IReadOnlyCollection GetConstraints() { - return _sparseFieldTableBuilder.Any() + return _sparseFieldTableBuilder.Count > 0 ? [new ExpressionInScope(null, new SparseFieldTableExpression(_sparseFieldTableBuilder.ToImmutable()))] : Array.Empty(); } diff --git a/src/JsonApiDotNetCore/Repositories/DataStoreUpdateException.cs b/src/JsonApiDotNetCore/Repositories/DataStoreUpdateException.cs index 4855c7fb6a..9fb9b482cd 100644 --- a/src/JsonApiDotNetCore/Repositories/DataStoreUpdateException.cs +++ b/src/JsonApiDotNetCore/Repositories/DataStoreUpdateException.cs @@ -6,4 +6,5 @@ namespace JsonApiDotNetCore.Repositories; /// The error that is thrown when the underlying data store is unable to persist changes. /// [PublicAPI] -public sealed class DataStoreUpdateException(Exception? innerException) : Exception("Failed to persist changes in the underlying data store.", innerException); +public sealed class DataStoreUpdateException(Exception? innerException) + : Exception("Failed to persist changes in the underlying data store.", innerException); diff --git a/src/JsonApiDotNetCore/Repositories/DbContextExtensions.cs b/src/JsonApiDotNetCore/Repositories/DbContextExtensions.cs index f78841defc..0e7089acec 100644 --- a/src/JsonApiDotNetCore/Repositories/DbContextExtensions.cs +++ b/src/JsonApiDotNetCore/Repositories/DbContextExtensions.cs @@ -13,8 +13,8 @@ public static class DbContextExtensions /// public static IIdentifiable GetTrackedOrAttach(this DbContext dbContext, IIdentifiable resource) { - ArgumentGuard.NotNull(dbContext); - ArgumentGuard.NotNull(resource); + ArgumentNullException.ThrowIfNull(dbContext); + ArgumentNullException.ThrowIfNull(resource); var trackedIdentifiable = (IIdentifiable?)dbContext.GetTrackedIdentifiable(resource); @@ -32,8 +32,8 @@ public static IIdentifiable GetTrackedOrAttach(this DbContext dbContext, IIdenti /// public static object? GetTrackedIdentifiable(this DbContext dbContext, IIdentifiable identifiable) { - ArgumentGuard.NotNull(dbContext); - ArgumentGuard.NotNull(identifiable); + ArgumentNullException.ThrowIfNull(dbContext); + ArgumentNullException.ThrowIfNull(identifiable); Type resourceClrType = identifiable.GetClrType(); string? stringId = identifiable.StringId; @@ -53,7 +53,7 @@ private static bool IsResource(EntityEntry entry, Type resourceClrType, string? /// public static void ResetChangeTracker(this DbContext dbContext) { - ArgumentGuard.NotNull(dbContext); + ArgumentNullException.ThrowIfNull(dbContext); dbContext.ChangeTracker.Clear(); } diff --git a/src/JsonApiDotNetCore/Repositories/DbContextResolver.cs b/src/JsonApiDotNetCore/Repositories/DbContextResolver.cs index bc275a96c1..c48169df72 100644 --- a/src/JsonApiDotNetCore/Repositories/DbContextResolver.cs +++ b/src/JsonApiDotNetCore/Repositories/DbContextResolver.cs @@ -15,7 +15,7 @@ public sealed class DbContextResolver : IDbContextResolver public DbContextResolver(TDbContext dbContext) { - ArgumentGuard.NotNull(dbContext); + ArgumentNullException.ThrowIfNull(dbContext); _dbContext = dbContext; } diff --git a/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs b/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs index 72eeff5c27..214987828a 100644 --- a/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs +++ b/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs @@ -31,12 +31,11 @@ namespace JsonApiDotNetCore.Repositories; public class EntityFrameworkCoreRepository : IResourceRepository, IRepositorySupportsTransaction where TResource : class, IIdentifiable { - private readonly CollectionConverter _collectionConverter = new(); private readonly ITargetedFields _targetedFields; private readonly DbContext _dbContext; private readonly IResourceGraph _resourceGraph; private readonly IResourceFactory _resourceFactory; - private readonly IEnumerable _constraintProviders; + private readonly IQueryConstraintProvider[] _constraintProviders; private readonly IResourceDefinitionAccessor _resourceDefinitionAccessor; private readonly TraceLogWriter> _traceWriter; @@ -47,19 +46,19 @@ public EntityFrameworkCoreRepository(ITargetedFields targetedFields, IDbContextR IResourceFactory resourceFactory, IEnumerable constraintProviders, ILoggerFactory loggerFactory, IResourceDefinitionAccessor resourceDefinitionAccessor) { - ArgumentGuard.NotNull(targetedFields); - ArgumentGuard.NotNull(dbContextResolver); - ArgumentGuard.NotNull(resourceGraph); - ArgumentGuard.NotNull(resourceFactory); - ArgumentGuard.NotNull(constraintProviders); - ArgumentGuard.NotNull(loggerFactory); - ArgumentGuard.NotNull(resourceDefinitionAccessor); + ArgumentNullException.ThrowIfNull(targetedFields); + ArgumentNullException.ThrowIfNull(dbContextResolver); + ArgumentNullException.ThrowIfNull(resourceGraph); + ArgumentNullException.ThrowIfNull(resourceFactory); + ArgumentNullException.ThrowIfNull(constraintProviders); + ArgumentNullException.ThrowIfNull(loggerFactory); + ArgumentNullException.ThrowIfNull(resourceDefinitionAccessor); _targetedFields = targetedFields; _dbContext = dbContextResolver.GetContext(); _resourceGraph = resourceGraph; _resourceFactory = resourceFactory; - _constraintProviders = constraintProviders; + _constraintProviders = constraintProviders as IQueryConstraintProvider[] ?? constraintProviders.ToArray(); _resourceDefinitionAccessor = resourceDefinitionAccessor; _traceWriter = new TraceLogWriter>(loggerFactory); } @@ -72,7 +71,7 @@ public virtual async Task> GetAsync(QueryLayer qu queryLayer }); - ArgumentGuard.NotNull(queryLayer); + ArgumentNullException.ThrowIfNull(queryLayer); using (CodeTimingSessionManager.Current.Measure("Repository - Get resource(s)")) { @@ -80,7 +79,8 @@ public virtual async Task> GetAsync(QueryLayer qu using (CodeTimingSessionManager.Current.Measure("Execute SQL (data)", MeasurementSettings.ExcludeDatabaseInPercentages)) { - return await query.ToListAsync(cancellationToken); + List resources = await query.ToListAsync(cancellationToken); + return resources.AsReadOnly(); } } } @@ -113,12 +113,14 @@ public virtual async Task CountAsync(FilterExpression? filter, Cancellation protected virtual IQueryable ApplyQueryLayer(QueryLayer queryLayer) { + ArgumentNullException.ThrowIfNull(queryLayer); + _traceWriter.LogMethodStart(new { queryLayer }); - ArgumentGuard.NotNull(queryLayer); + ArgumentNullException.ThrowIfNull(queryLayer); using (CodeTimingSessionManager.Current.Measure("Convert QueryLayer to System.Expression")) { @@ -187,7 +189,7 @@ public virtual Task GetForCreateAsync(Type resourceClrType, [Disallow id }); - ArgumentGuard.NotNull(resourceClrType); + ArgumentNullException.ThrowIfNull(resourceClrType); var resource = (TResource)_resourceFactory.CreateInstance(resourceClrType); resource.Id = id; @@ -204,8 +206,8 @@ public virtual async Task CreateAsync(TResource resourceFromRequest, TResource r resourceForDatabase }); - ArgumentGuard.NotNull(resourceFromRequest); - ArgumentGuard.NotNull(resourceForDatabase); + ArgumentNullException.ThrowIfNull(resourceFromRequest); + ArgumentNullException.ThrowIfNull(resourceForDatabase); using IDisposable _ = CodeTimingSessionManager.Current.Measure("Repository - Create resource"); @@ -247,7 +249,7 @@ public virtual async Task CreateAsync(TResource resourceFromRequest, TResource r if (relationship is HasManyAttribute hasManyRelationship) { - HashSet rightResourceIds = _collectionConverter.ExtractResources(rightValue).ToHashSet(IdentifiableComparer.Instance); + HashSet rightResourceIds = CollectionConverter.Instance.ExtractResources(rightValue).ToHashSet(IdentifiableComparer.Instance); await _resourceDefinitionAccessor.OnSetToManyRelationshipAsync(leftResource, hasManyRelationship, rightResourceIds, writeOperation, cancellationToken); @@ -266,7 +268,7 @@ await _resourceDefinitionAccessor.OnSetToManyRelationshipAsync(leftResource, has queryLayer }); - ArgumentGuard.NotNull(queryLayer); + ArgumentNullException.ThrowIfNull(queryLayer); using IDisposable _ = CodeTimingSessionManager.Current.Measure("Repository - Get resource for update"); @@ -283,8 +285,8 @@ public virtual async Task UpdateAsync(TResource resourceFromRequest, TResource r resourceFromDatabase }); - ArgumentGuard.NotNull(resourceFromRequest); - ArgumentGuard.NotNull(resourceFromDatabase); + ArgumentNullException.ThrowIfNull(resourceFromRequest); + ArgumentNullException.ThrowIfNull(resourceFromDatabase); using IDisposable _ = CodeTimingSessionManager.Current.Measure("Repository - Update resource"); @@ -316,6 +318,8 @@ public virtual async Task UpdateAsync(TResource resourceFromRequest, TResource r protected void AssertIsNotClearingRequiredToOneRelationship(RelationshipAttribute relationship, object? rightValue) { + ArgumentNullException.ThrowIfNull(relationship); + if (relationship is HasOneAttribute) { INavigation? navigation = GetNavigation(relationship); @@ -411,7 +415,7 @@ public virtual async Task SetRelationshipAsync(TResource leftResource, object? r rightValue }); - ArgumentGuard.NotNull(leftResource); + ArgumentNullException.ThrowIfNull(leftResource); using IDisposable _ = CodeTimingSessionManager.Current.Measure("Repository - Set relationship"); @@ -442,7 +446,7 @@ public virtual async Task AddToToManyRelationshipAsync(TResource? leftResource, rightResourceIds }); - ArgumentGuard.NotNull(rightResourceIds); + ArgumentNullException.ThrowIfNull(rightResourceIds); using IDisposable _ = CodeTimingSessionManager.Current.Measure("Repository - Add to to-many relationship"); @@ -455,10 +459,10 @@ public virtual async Task AddToToManyRelationshipAsync(TResource? leftResource, await _resourceDefinitionAccessor.OnAddToRelationshipAsync(leftPlaceholderResource, relationship, rightResourceIds, cancellationToken); - if (rightResourceIds.Any()) + if (rightResourceIds.Count > 0) { var leftResourceTracked = (TResource)_dbContext.GetTrackedOrAttach(leftPlaceholderResource); - IEnumerable rightValueToStore = GetRightValueToStoreForAddToToMany(leftResourceTracked, relationship, rightResourceIds); + ISet rightValueToStore = GetRightValueToStoreForAddToToMany(leftResourceTracked, relationship, rightResourceIds); await UpdateRelationshipAsync(relationship, leftResourceTracked, rightValueToStore, cancellationToken); @@ -471,22 +475,23 @@ public virtual async Task AddToToManyRelationshipAsync(TResource? leftResource, } } - private IEnumerable GetRightValueToStoreForAddToToMany(TResource leftResource, HasManyAttribute relationship, ISet rightResourceIdsToAdd) + private ISet GetRightValueToStoreForAddToToMany(TResource leftResource, HasManyAttribute relationship, + ISet rightResourceIdsToAdd) { object? rightValueStored = relationship.GetValue(leftResource); // @formatter:wrap_chained_method_calls chop_always - // @formatter:wrap_before_first_method_call true + // @formatter:wrap_after_property_in_chained_method_calls true - HashSet rightResourceIdsStored = _collectionConverter + HashSet rightResourceIdsStored = CollectionConverter.Instance .ExtractResources(rightValueStored) - .Select(rightResource => _dbContext.GetTrackedOrAttach(rightResource)) + .Select(_dbContext.GetTrackedOrAttach) .ToHashSet(IdentifiableComparer.Instance); - // @formatter:wrap_before_first_method_call restore + // @formatter:wrap_after_property_in_chained_method_calls restore // @formatter:wrap_chained_method_calls restore - if (rightResourceIdsStored.Any()) + if (rightResourceIdsStored.Count > 0) { rightResourceIdsStored.UnionWith(rightResourceIdsToAdd); return rightResourceIdsStored; @@ -505,8 +510,8 @@ public virtual async Task RemoveFromToManyRelationshipAsync(TResource leftResour rightResourceIds }); - ArgumentGuard.NotNull(leftResource); - ArgumentGuard.NotNull(rightResourceIds); + ArgumentNullException.ThrowIfNull(leftResource); + ArgumentNullException.ThrowIfNull(rightResourceIds); using IDisposable _ = CodeTimingSessionManager.Current.Measure("Repository - Remove from to-many relationship"); @@ -515,7 +520,7 @@ public virtual async Task RemoveFromToManyRelationshipAsync(TResource leftResour await _resourceDefinitionAccessor.OnRemoveFromRelationshipAsync(leftResource, relationship, rightResourceIdsToRemove, cancellationToken); - if (rightResourceIdsToRemove.Any()) + if (rightResourceIdsToRemove.Count > 0) { var leftResourceTracked = (TResource)_dbContext.GetTrackedOrAttach(leftResource); @@ -525,18 +530,18 @@ public virtual async Task RemoveFromToManyRelationshipAsync(TResource leftResour object? rightValueStored = relationship.GetValue(leftResourceTracked); // @formatter:wrap_chained_method_calls chop_always - // @formatter:wrap_before_first_method_call true + // @formatter:wrap_after_property_in_chained_method_calls true - IIdentifiable[] rightResourceIdsStored = _collectionConverter + IIdentifiable[] rightResourceIdsStored = CollectionConverter.Instance .ExtractResources(rightValueStored) .Concat(extraResourceIdsToRemove) - .Select(rightResource => _dbContext.GetTrackedOrAttach(rightResource)) + .Select(_dbContext.GetTrackedOrAttach) .ToArray(); - // @formatter:wrap_before_first_method_call restore + // @formatter:wrap_after_property_in_chained_method_calls restore // @formatter:wrap_chained_method_calls restore - rightValueStored = _collectionConverter.CopyToTypedCollection(rightResourceIdsStored, relationship.Property.PropertyType); + rightValueStored = CollectionConverter.Instance.CopyToTypedCollection(rightResourceIdsStored, relationship.Property.PropertyType); relationship.SetValue(leftResourceTracked, rightValueStored); MarkRelationshipAsLoaded(leftResourceTracked, relationship); @@ -576,7 +581,7 @@ private void MarkManyToManyRelationshipAsLoaded(EntityEntry leftEntry string[] foreignKeyNames = skipNavigation.ForeignKey.Properties.Select(property => property.Name).ToArray(); - foreach (EntityEntry joinEntry in _dbContext.ChangeTracker.Entries().Where(entry => entry.Metadata == skipNavigation.JoinEntityType).ToList()) + foreach (EntityEntry joinEntry in _dbContext.ChangeTracker.Entries().Where(entry => entry.Metadata == skipNavigation.JoinEntityType).ToArray()) { object?[] foreignKeyValues = GetCurrentKeyValues(joinEntry, foreignKeyNames); @@ -595,6 +600,9 @@ private void MarkManyToManyRelationshipAsLoaded(EntityEntry leftEntry protected async Task UpdateRelationshipAsync(RelationshipAttribute relationship, TResource leftResource, object? valueToAssign, CancellationToken cancellationToken) { + ArgumentNullException.ThrowIfNull(relationship); + ArgumentNullException.ThrowIfNull(leftResource); + object? trackedValueToAssign = EnsureRelationshipValueToAssignIsTracked(valueToAssign, relationship.Property.PropertyType); if (RequireLoadOfInverseRelationship(relationship, trackedValueToAssign)) @@ -615,11 +623,11 @@ protected async Task UpdateRelationshipAsync(RelationshipAttribute relationship, return null; } - IReadOnlyCollection rightResources = _collectionConverter.ExtractResources(rightValue); - IIdentifiable[] rightResourcesTracked = rightResources.Select(rightResource => _dbContext.GetTrackedOrAttach(rightResource)).ToArray(); + IReadOnlyCollection rightResources = CollectionConverter.Instance.ExtractResources(rightValue); + IIdentifiable[] rightResourcesTracked = rightResources.Select(_dbContext.GetTrackedOrAttach).ToArray(); return rightValue is IEnumerable - ? _collectionConverter.CopyToTypedCollection(rightResourcesTracked, relationshipPropertyType) + ? CollectionConverter.Instance.CopyToTypedCollection(rightResourcesTracked, relationshipPropertyType) : rightResourcesTracked.Single(); } diff --git a/src/JsonApiDotNetCore/Repositories/IResourceRepositoryAccessor.cs b/src/JsonApiDotNetCore/Repositories/IResourceRepositoryAccessor.cs index a58542c239..df08f04f26 100644 --- a/src/JsonApiDotNetCore/Repositories/IResourceRepositoryAccessor.cs +++ b/src/JsonApiDotNetCore/Repositories/IResourceRepositoryAccessor.cs @@ -11,6 +11,11 @@ namespace JsonApiDotNetCore.Repositories; /// public interface IResourceRepositoryAccessor { + /// + /// Uses the to lookup the corresponding for the specified CLR type. + /// + ResourceType LookupResourceType(Type resourceClrType); + /// /// Invokes for the specified resource type. /// diff --git a/src/JsonApiDotNetCore/Repositories/ResourceRepositoryAccessor.cs b/src/JsonApiDotNetCore/Repositories/ResourceRepositoryAccessor.cs index 6f19f51c1d..4e3b5163a3 100644 --- a/src/JsonApiDotNetCore/Repositories/ResourceRepositoryAccessor.cs +++ b/src/JsonApiDotNetCore/Repositories/ResourceRepositoryAccessor.cs @@ -20,19 +20,29 @@ public class ResourceRepositoryAccessor : IResourceRepositoryAccessor public ResourceRepositoryAccessor(IServiceProvider serviceProvider, IResourceGraph resourceGraph, IJsonApiRequest request) { - ArgumentGuard.NotNull(serviceProvider); - ArgumentGuard.NotNull(resourceGraph); - ArgumentGuard.NotNull(request); + ArgumentNullException.ThrowIfNull(serviceProvider); + ArgumentNullException.ThrowIfNull(resourceGraph); + ArgumentNullException.ThrowIfNull(request); _serviceProvider = serviceProvider; _resourceGraph = resourceGraph; _request = request; } + /// + public ResourceType LookupResourceType(Type resourceClrType) + { + ArgumentNullException.ThrowIfNull(resourceClrType); + + return _resourceGraph.GetResourceType(resourceClrType); + } + /// public async Task> GetAsync(QueryLayer queryLayer, CancellationToken cancellationToken) where TResource : class, IIdentifiable { + ArgumentNullException.ThrowIfNull(queryLayer); + dynamic repository = ResolveReadRepository(typeof(TResource)); return (IReadOnlyCollection)await repository.GetAsync(queryLayer, cancellationToken); } @@ -40,7 +50,8 @@ public async Task> GetAsync(QueryLayer /// public async Task> GetAsync(ResourceType resourceType, QueryLayer queryLayer, CancellationToken cancellationToken) { - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(resourceType); + ArgumentNullException.ThrowIfNull(queryLayer); dynamic repository = ResolveReadRepository(resourceType); return (IReadOnlyCollection)await repository.GetAsync(queryLayer, cancellationToken); @@ -49,6 +60,8 @@ public async Task> GetAsync(ResourceType reso /// public async Task CountAsync(ResourceType resourceType, FilterExpression? filter, CancellationToken cancellationToken) { + ArgumentNullException.ThrowIfNull(resourceType); + dynamic repository = ResolveReadRepository(resourceType); return (int)await repository.CountAsync(filter, cancellationToken); } @@ -57,6 +70,8 @@ public async Task CountAsync(ResourceType resourceType, FilterExpression? f public async Task GetForCreateAsync(Type resourceClrType, [DisallowNull] TId id, CancellationToken cancellationToken) where TResource : class, IIdentifiable { + ArgumentNullException.ThrowIfNull(resourceClrType); + dynamic repository = GetWriteRepository(typeof(TResource)); return await repository.GetForCreateAsync(resourceClrType, id, cancellationToken); } @@ -65,6 +80,9 @@ public async Task GetForCreateAsync(Type resourceClrT public async Task CreateAsync(TResource resourceFromRequest, TResource resourceForDatabase, CancellationToken cancellationToken) where TResource : class, IIdentifiable { + ArgumentNullException.ThrowIfNull(resourceFromRequest); + ArgumentNullException.ThrowIfNull(resourceForDatabase); + dynamic repository = GetWriteRepository(typeof(TResource)); await repository.CreateAsync(resourceFromRequest, resourceForDatabase, cancellationToken); } @@ -73,6 +91,8 @@ public async Task CreateAsync(TResource resourceFromRequest, TResourc public async Task GetForUpdateAsync(QueryLayer queryLayer, CancellationToken cancellationToken) where TResource : class, IIdentifiable { + ArgumentNullException.ThrowIfNull(queryLayer); + dynamic repository = GetWriteRepository(typeof(TResource)); return await repository.GetForUpdateAsync(queryLayer, cancellationToken); } @@ -81,6 +101,9 @@ public async Task CreateAsync(TResource resourceFromRequest, TResourc public async Task UpdateAsync(TResource resourceFromRequest, TResource resourceFromDatabase, CancellationToken cancellationToken) where TResource : class, IIdentifiable { + ArgumentNullException.ThrowIfNull(resourceFromRequest); + ArgumentNullException.ThrowIfNull(resourceFromDatabase); + dynamic repository = GetWriteRepository(typeof(TResource)); await repository.UpdateAsync(resourceFromRequest, resourceFromDatabase, cancellationToken); } @@ -97,6 +120,8 @@ public async Task DeleteAsync(TResource? resourceFromDatabase, [ public async Task SetRelationshipAsync(TResource leftResource, object? rightValue, CancellationToken cancellationToken) where TResource : class, IIdentifiable { + ArgumentNullException.ThrowIfNull(leftResource); + dynamic repository = GetWriteRepository(typeof(TResource)); await repository.SetRelationshipAsync(leftResource, rightValue, cancellationToken); } @@ -106,6 +131,8 @@ public async Task AddToToManyRelationshipAsync(TResource? leftRe CancellationToken cancellationToken) where TResource : class, IIdentifiable { + ArgumentNullException.ThrowIfNull(rightResourceIds); + dynamic repository = GetWriteRepository(typeof(TResource)); await repository.AddToToManyRelationshipAsync(leftResource, leftId, rightResourceIds, cancellationToken); } @@ -115,18 +142,25 @@ public async Task RemoveFromToManyRelationshipAsync(TResource leftRes CancellationToken cancellationToken) where TResource : class, IIdentifiable { + ArgumentNullException.ThrowIfNull(leftResource); + ArgumentNullException.ThrowIfNull(rightResourceIds); + dynamic repository = GetWriteRepository(typeof(TResource)); await repository.RemoveFromToManyRelationshipAsync(leftResource, rightResourceIds, cancellationToken); } protected object ResolveReadRepository(Type resourceClrType) { + ArgumentNullException.ThrowIfNull(resourceClrType); + ResourceType resourceType = _resourceGraph.GetResourceType(resourceClrType); return ResolveReadRepository(resourceType); } protected virtual object ResolveReadRepository(ResourceType resourceType) { + ArgumentNullException.ThrowIfNull(resourceType); + Type repositoryType = typeof(IResourceReadRepository<,>).MakeGenericType(resourceType.ClrType, resourceType.IdentityClrType); return _serviceProvider.GetRequiredService(repositoryType); } @@ -154,6 +188,8 @@ private object GetWriteRepository(Type resourceClrType) protected virtual object ResolveWriteRepository(Type resourceClrType) { + ArgumentNullException.ThrowIfNull(resourceClrType); + ResourceType resourceType = _resourceGraph.GetResourceType(resourceClrType); Type resourceDefinitionType = typeof(IResourceWriteRepository<,>).MakeGenericType(resourceType.ClrType, resourceType.IdentityClrType); diff --git a/src/JsonApiDotNetCore/Resources/AbstractResourceWrapper.cs b/src/JsonApiDotNetCore/Resources/AbstractResourceWrapper.cs index c3a193d3cd..3cf6233cf2 100644 --- a/src/JsonApiDotNetCore/Resources/AbstractResourceWrapper.cs +++ b/src/JsonApiDotNetCore/Resources/AbstractResourceWrapper.cs @@ -8,7 +8,7 @@ internal sealed class AbstractResourceWrapper : Identifiable, IAbstrac public AbstractResourceWrapper(Type abstractType) { - ArgumentGuard.NotNull(abstractType); + ArgumentNullException.ThrowIfNull(abstractType); AbstractType = abstractType; } diff --git a/src/JsonApiDotNetCore/Resources/IdentifiableExtensions.cs b/src/JsonApiDotNetCore/Resources/IdentifiableExtensions.cs index 34af2f36fe..d4e3c156cb 100644 --- a/src/JsonApiDotNetCore/Resources/IdentifiableExtensions.cs +++ b/src/JsonApiDotNetCore/Resources/IdentifiableExtensions.cs @@ -8,7 +8,7 @@ internal static class IdentifiableExtensions public static object GetTypedId(this IIdentifiable identifiable) { - ArgumentGuard.NotNull(identifiable); + ArgumentNullException.ThrowIfNull(identifiable); PropertyInfo? property = identifiable.GetClrType().GetProperty(IdPropertyName); @@ -18,17 +18,12 @@ public static object GetTypedId(this IIdentifiable identifiable) } object? propertyValue = property.GetValue(identifiable); + object? defaultValue = RuntimeTypeConverter.GetDefaultValue(property.PropertyType); - // PERF: We want to throw when 'Id' is unassigned without doing an expensive reflection call, unless this is likely the case. - if (identifiable.StringId == null) + if (Equals(propertyValue, defaultValue)) { - object? defaultValue = RuntimeTypeConverter.GetDefaultValue(property.PropertyType); - - if (Equals(propertyValue, defaultValue)) - { - throw new InvalidOperationException($"Property '{identifiable.GetClrType().Name}.{IdPropertyName}' should " + - $"have been assigned at this point, but it contains its default {property.PropertyType.Name} value '{propertyValue}'."); - } + throw new InvalidOperationException($"Property '{identifiable.GetClrType().Name}.{IdPropertyName}' should " + + $"have been assigned at this point, but it contains its default {property.PropertyType.Name} value '{propertyValue}'."); } return propertyValue!; @@ -36,7 +31,7 @@ public static object GetTypedId(this IIdentifiable identifiable) public static Type GetClrType(this IIdentifiable identifiable) { - ArgumentGuard.NotNull(identifiable); + ArgumentNullException.ThrowIfNull(identifiable); return identifiable is IAbstractResourceWrapper abstractResource ? abstractResource.AbstractType : identifiable.GetType(); } diff --git a/src/JsonApiDotNetCore/Resources/JsonApiResourceDefinition.cs b/src/JsonApiDotNetCore/Resources/JsonApiResourceDefinition.cs index f069c155e8..e2a354ca76 100644 --- a/src/JsonApiDotNetCore/Resources/JsonApiResourceDefinition.cs +++ b/src/JsonApiDotNetCore/Resources/JsonApiResourceDefinition.cs @@ -26,7 +26,7 @@ public class JsonApiResourceDefinition : IResourceDefinition(); diff --git a/src/JsonApiDotNetCore/Resources/OperationContainer.cs b/src/JsonApiDotNetCore/Resources/OperationContainer.cs index 88ea29ecdc..dd2cfe2630 100644 --- a/src/JsonApiDotNetCore/Resources/OperationContainer.cs +++ b/src/JsonApiDotNetCore/Resources/OperationContainer.cs @@ -10,17 +10,15 @@ namespace JsonApiDotNetCore.Resources; [PublicAPI] public sealed class OperationContainer { - private static readonly CollectionConverter CollectionConverter = new(); - public IIdentifiable Resource { get; } public ITargetedFields TargetedFields { get; } public IJsonApiRequest Request { get; } public OperationContainer(IIdentifiable resource, ITargetedFields targetedFields, IJsonApiRequest request) { - ArgumentGuard.NotNull(resource); - ArgumentGuard.NotNull(targetedFields); - ArgumentGuard.NotNull(request); + ArgumentNullException.ThrowIfNull(resource); + ArgumentNullException.ThrowIfNull(targetedFields); + ArgumentNullException.ThrowIfNull(request); Resource = resource; TargetedFields = targetedFields; @@ -34,7 +32,7 @@ public void SetTransactionId(string transactionId) public OperationContainer WithResource(IIdentifiable resource) { - ArgumentGuard.NotNull(resource); + ArgumentNullException.ThrowIfNull(resource); return new OperationContainer(resource, TargetedFields, Request); } @@ -56,7 +54,7 @@ public ISet GetSecondaryResources() private void AddSecondaryResources(RelationshipAttribute relationship, HashSet secondaryResources) { object? rightValue = relationship.GetValue(Resource); - IReadOnlyCollection rightResources = CollectionConverter.ExtractResources(rightValue); + IReadOnlyCollection rightResources = CollectionConverter.Instance.ExtractResources(rightValue); secondaryResources.UnionWith(rightResources); } diff --git a/src/JsonApiDotNetCore/Resources/ResourceChangeTracker.cs b/src/JsonApiDotNetCore/Resources/ResourceChangeTracker.cs index 7eb57813ca..c17ce60b45 100644 --- a/src/JsonApiDotNetCore/Resources/ResourceChangeTracker.cs +++ b/src/JsonApiDotNetCore/Resources/ResourceChangeTracker.cs @@ -12,14 +12,14 @@ public sealed class ResourceChangeTracker : IResourceChangeTracker? _initiallyStoredAttributeValues; - private IDictionary? _requestAttributeValues; - private IDictionary? _finallyStoredAttributeValues; + private Dictionary? _initiallyStoredAttributeValues; + private Dictionary? _requestAttributeValues; + private Dictionary? _finallyStoredAttributeValues; public ResourceChangeTracker(IJsonApiRequest request, ITargetedFields targetedFields) { - ArgumentGuard.NotNull(request); - ArgumentGuard.NotNull(targetedFields); + ArgumentNullException.ThrowIfNull(request); + ArgumentNullException.ThrowIfNull(targetedFields); _request = request; _targetedFields = targetedFields; @@ -28,7 +28,7 @@ public ResourceChangeTracker(IJsonApiRequest request, ITargetedFields targetedFi /// public void SetInitiallyStoredAttributeValues(TResource resource) { - ArgumentGuard.NotNull(resource); + ArgumentNullException.ThrowIfNull(resource); _initiallyStoredAttributeValues = CreateAttributeDictionary(resource, _request.PrimaryResourceType!.Attributes); } @@ -36,7 +36,7 @@ public void SetInitiallyStoredAttributeValues(TResource resource) /// public void SetRequestAttributeValues(TResource resource) { - ArgumentGuard.NotNull(resource); + ArgumentNullException.ThrowIfNull(resource); _requestAttributeValues = CreateAttributeDictionary(resource, _targetedFields.Attributes); } @@ -44,12 +44,12 @@ public void SetRequestAttributeValues(TResource resource) /// public void SetFinallyStoredAttributeValues(TResource resource) { - ArgumentGuard.NotNull(resource); + ArgumentNullException.ThrowIfNull(resource); _finallyStoredAttributeValues = CreateAttributeDictionary(resource, _request.PrimaryResourceType!.Attributes); } - private IDictionary CreateAttributeDictionary(TResource resource, IEnumerable attributes) + private Dictionary CreateAttributeDictionary(TResource resource, IEnumerable attributes) { var result = new Dictionary(); diff --git a/src/JsonApiDotNetCore/Resources/ResourceDefinitionAccessor.cs b/src/JsonApiDotNetCore/Resources/ResourceDefinitionAccessor.cs index 93b71a5546..a225766fb5 100644 --- a/src/JsonApiDotNetCore/Resources/ResourceDefinitionAccessor.cs +++ b/src/JsonApiDotNetCore/Resources/ResourceDefinitionAccessor.cs @@ -33,8 +33,8 @@ public bool IsReadOnlyRequest public ResourceDefinitionAccessor(IResourceGraph resourceGraph, IServiceProvider serviceProvider) { - ArgumentGuard.NotNull(resourceGraph); - ArgumentGuard.NotNull(serviceProvider); + ArgumentNullException.ThrowIfNull(resourceGraph); + ArgumentNullException.ThrowIfNull(serviceProvider); _resourceGraph = resourceGraph; _serviceProvider = serviceProvider; @@ -43,7 +43,7 @@ public ResourceDefinitionAccessor(IResourceGraph resourceGraph, IServiceProvider /// public IImmutableSet OnApplyIncludes(ResourceType resourceType, IImmutableSet existingIncludes) { - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(resourceType); dynamic resourceDefinition = ResolveResourceDefinition(resourceType); return resourceDefinition.OnApplyIncludes(existingIncludes); @@ -52,7 +52,7 @@ public IImmutableSet OnApplyIncludes(ResourceType reso /// public FilterExpression? OnApplyFilter(ResourceType resourceType, FilterExpression? existingFilter) { - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(resourceType); dynamic resourceDefinition = ResolveResourceDefinition(resourceType); return resourceDefinition.OnApplyFilter(existingFilter); @@ -61,7 +61,7 @@ public IImmutableSet OnApplyIncludes(ResourceType reso /// public SortExpression? OnApplySort(ResourceType resourceType, SortExpression? existingSort) { - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(resourceType); dynamic resourceDefinition = ResolveResourceDefinition(resourceType); return resourceDefinition.OnApplySort(existingSort); @@ -70,7 +70,7 @@ public IImmutableSet OnApplyIncludes(ResourceType reso /// public PaginationExpression? OnApplyPagination(ResourceType resourceType, PaginationExpression? existingPagination) { - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(resourceType); dynamic resourceDefinition = ResolveResourceDefinition(resourceType); return resourceDefinition.OnApplyPagination(existingPagination); @@ -79,7 +79,7 @@ public IImmutableSet OnApplyIncludes(ResourceType reso /// public SparseFieldSetExpression? OnApplySparseFieldSet(ResourceType resourceType, SparseFieldSetExpression? existingSparseFieldSet) { - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(resourceType); dynamic resourceDefinition = ResolveResourceDefinition(resourceType); return resourceDefinition.OnApplySparseFieldSet(existingSparseFieldSet); @@ -88,11 +88,11 @@ public IImmutableSet OnApplyIncludes(ResourceType reso /// public object? GetQueryableHandlerForQueryStringParameter(Type resourceClrType, string parameterName) { - ArgumentGuard.NotNull(resourceClrType); - ArgumentGuard.NotNullNorEmpty(parameterName); + ArgumentNullException.ThrowIfNull(resourceClrType); + ArgumentException.ThrowIfNullOrEmpty(parameterName); dynamic resourceDefinition = ResolveResourceDefinition(resourceClrType); - dynamic handlers = resourceDefinition.OnRegisterQueryableHandlersForQueryStringParameters(); + dynamic? handlers = resourceDefinition.OnRegisterQueryableHandlersForQueryStringParameters(); if (handlers != null) { @@ -108,7 +108,7 @@ public IImmutableSet OnApplyIncludes(ResourceType reso /// public IDictionary? GetMeta(ResourceType resourceType, IIdentifiable resourceInstance) { - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(resourceType); dynamic resourceDefinition = ResolveResourceDefinition(resourceType); return resourceDefinition.GetMeta((dynamic)resourceInstance); @@ -118,7 +118,7 @@ public IImmutableSet OnApplyIncludes(ResourceType reso public async Task OnPrepareWriteAsync(TResource resource, WriteOperationKind writeOperation, CancellationToken cancellationToken) where TResource : class, IIdentifiable { - ArgumentGuard.NotNull(resource); + ArgumentNullException.ThrowIfNull(resource); dynamic resourceDefinition = ResolveResourceDefinition(resource.GetClrType()); await resourceDefinition.OnPrepareWriteAsync((dynamic)resource, writeOperation, cancellationToken); @@ -129,8 +129,8 @@ public async Task OnPrepareWriteAsync(TResource resource, WriteOperat IIdentifiable? rightResourceId, WriteOperationKind writeOperation, CancellationToken cancellationToken) where TResource : class, IIdentifiable { - ArgumentGuard.NotNull(leftResource); - ArgumentGuard.NotNull(hasOneRelationship); + ArgumentNullException.ThrowIfNull(leftResource); + ArgumentNullException.ThrowIfNull(hasOneRelationship); dynamic resourceDefinition = ResolveResourceDefinition(leftResource.GetClrType()); @@ -143,9 +143,9 @@ public async Task OnSetToManyRelationshipAsync(TResource leftResource ISet rightResourceIds, WriteOperationKind writeOperation, CancellationToken cancellationToken) where TResource : class, IIdentifiable { - ArgumentGuard.NotNull(leftResource); - ArgumentGuard.NotNull(hasManyRelationship); - ArgumentGuard.NotNull(rightResourceIds); + ArgumentNullException.ThrowIfNull(leftResource); + ArgumentNullException.ThrowIfNull(hasManyRelationship); + ArgumentNullException.ThrowIfNull(rightResourceIds); dynamic resourceDefinition = ResolveResourceDefinition(leftResource.GetClrType()); await resourceDefinition.OnSetToManyRelationshipAsync((dynamic)leftResource, hasManyRelationship, rightResourceIds, writeOperation, cancellationToken); @@ -156,8 +156,8 @@ public async Task OnAddToRelationshipAsync(TResource leftResource, Ha CancellationToken cancellationToken) where TResource : class, IIdentifiable { - ArgumentGuard.NotNull(hasManyRelationship); - ArgumentGuard.NotNull(rightResourceIds); + ArgumentNullException.ThrowIfNull(hasManyRelationship); + ArgumentNullException.ThrowIfNull(rightResourceIds); dynamic resourceDefinition = ResolveResourceDefinition(leftResource.GetClrType()); await resourceDefinition.OnAddToRelationshipAsync((dynamic)leftResource, hasManyRelationship, rightResourceIds, cancellationToken); @@ -168,9 +168,9 @@ public async Task OnRemoveFromRelationshipAsync(TResource leftResourc ISet rightResourceIds, CancellationToken cancellationToken) where TResource : class, IIdentifiable { - ArgumentGuard.NotNull(leftResource); - ArgumentGuard.NotNull(hasManyRelationship); - ArgumentGuard.NotNull(rightResourceIds); + ArgumentNullException.ThrowIfNull(leftResource); + ArgumentNullException.ThrowIfNull(hasManyRelationship); + ArgumentNullException.ThrowIfNull(rightResourceIds); dynamic resourceDefinition = ResolveResourceDefinition(leftResource.GetClrType()); await resourceDefinition.OnRemoveFromRelationshipAsync((dynamic)leftResource, hasManyRelationship, rightResourceIds, cancellationToken); @@ -180,7 +180,7 @@ public async Task OnRemoveFromRelationshipAsync(TResource leftResourc public async Task OnWritingAsync(TResource resource, WriteOperationKind writeOperation, CancellationToken cancellationToken) where TResource : class, IIdentifiable { - ArgumentGuard.NotNull(resource); + ArgumentNullException.ThrowIfNull(resource); dynamic resourceDefinition = ResolveResourceDefinition(resource.GetClrType()); await resourceDefinition.OnWritingAsync((dynamic)resource, writeOperation, cancellationToken); @@ -190,7 +190,7 @@ public async Task OnWritingAsync(TResource resource, WriteOperationKi public async Task OnWriteSucceededAsync(TResource resource, WriteOperationKind writeOperation, CancellationToken cancellationToken) where TResource : class, IIdentifiable { - ArgumentGuard.NotNull(resource); + ArgumentNullException.ThrowIfNull(resource); dynamic resourceDefinition = ResolveResourceDefinition(resource.GetClrType()); await resourceDefinition.OnWriteSucceededAsync((dynamic)resource, writeOperation, cancellationToken); @@ -199,7 +199,7 @@ public async Task OnWriteSucceededAsync(TResource resource, WriteOper /// public void OnDeserialize(IIdentifiable resource) { - ArgumentGuard.NotNull(resource); + ArgumentNullException.ThrowIfNull(resource); dynamic resourceDefinition = ResolveResourceDefinition(resource.GetClrType()); resourceDefinition.OnDeserialize((dynamic)resource); @@ -208,7 +208,7 @@ public void OnDeserialize(IIdentifiable resource) /// public void OnSerialize(IIdentifiable resource) { - ArgumentGuard.NotNull(resource); + ArgumentNullException.ThrowIfNull(resource); dynamic resourceDefinition = ResolveResourceDefinition(resource.GetClrType()); resourceDefinition.OnSerialize((dynamic)resource); @@ -216,12 +216,16 @@ public void OnSerialize(IIdentifiable resource) protected object ResolveResourceDefinition(Type resourceClrType) { + ArgumentNullException.ThrowIfNull(resourceClrType); + ResourceType resourceType = _resourceGraph.GetResourceType(resourceClrType); return ResolveResourceDefinition(resourceType); } protected virtual object ResolveResourceDefinition(ResourceType resourceType) { + ArgumentNullException.ThrowIfNull(resourceType); + Type resourceDefinitionType = typeof(IResourceDefinition<,>).MakeGenericType(resourceType.ClrType, resourceType.IdentityClrType); return _serviceProvider.GetRequiredService(resourceDefinitionType); } diff --git a/src/JsonApiDotNetCore/Resources/ResourceFactory.cs b/src/JsonApiDotNetCore/Resources/ResourceFactory.cs index f8af9dfa2f..5a18763939 100644 --- a/src/JsonApiDotNetCore/Resources/ResourceFactory.cs +++ b/src/JsonApiDotNetCore/Resources/ResourceFactory.cs @@ -15,7 +15,7 @@ internal sealed class ResourceFactory : IResourceFactory public ResourceFactory(IServiceProvider serviceProvider) { - ArgumentGuard.NotNull(serviceProvider); + ArgumentNullException.ThrowIfNull(serviceProvider); _serviceProvider = serviceProvider; } @@ -23,7 +23,7 @@ public ResourceFactory(IServiceProvider serviceProvider) /// public IIdentifiable CreateInstance(Type resourceClrType) { - ArgumentGuard.NotNull(resourceClrType); + ArgumentNullException.ThrowIfNull(resourceClrType); if (!resourceClrType.IsAssignableTo(typeof(IIdentifiable))) { @@ -85,14 +85,14 @@ private static IIdentifiable InnerCreateInstance(Type type, IServiceProvider ser /// public NewExpression CreateNewExpression(Type resourceClrType) { - ArgumentGuard.NotNull(resourceClrType); + ArgumentNullException.ThrowIfNull(resourceClrType); if (HasSingleConstructorWithoutParameters(resourceClrType)) { return Expression.New(resourceClrType); } - var constructorArguments = new List(); + List constructorArguments = []; ConstructorInfo longestConstructor = GetLongestConstructor(resourceClrType); diff --git a/src/JsonApiDotNetCore/Resources/SortExpressionLambdaConverter.cs b/src/JsonApiDotNetCore/Resources/SortExpressionLambdaConverter.cs index 8696195e28..97e014f344 100644 --- a/src/JsonApiDotNetCore/Resources/SortExpressionLambdaConverter.cs +++ b/src/JsonApiDotNetCore/Resources/SortExpressionLambdaConverter.cs @@ -11,18 +11,18 @@ namespace JsonApiDotNetCore.Resources; internal sealed class SortExpressionLambdaConverter { private readonly IResourceGraph _resourceGraph; - private readonly IList _fields = new List(); + private readonly List _fields = []; public SortExpressionLambdaConverter(IResourceGraph resourceGraph) { - ArgumentGuard.NotNull(resourceGraph); + ArgumentNullException.ThrowIfNull(resourceGraph); _resourceGraph = resourceGraph; } public SortElementExpression FromLambda(Expression> keySelector, ListSortDirection sortDirection) { - ArgumentGuard.NotNull(keySelector); + ArgumentNullException.ThrowIfNull(keySelector); _fields.Clear(); diff --git a/src/JsonApiDotNetCore/Resources/TargetedFields.cs b/src/JsonApiDotNetCore/Resources/TargetedFields.cs index 2e841873b2..420058106f 100644 --- a/src/JsonApiDotNetCore/Resources/TargetedFields.cs +++ b/src/JsonApiDotNetCore/Resources/TargetedFields.cs @@ -7,8 +7,8 @@ namespace JsonApiDotNetCore.Resources; [PublicAPI] public sealed class TargetedFields : ITargetedFields { - IReadOnlySet ITargetedFields.Attributes => Attributes; - IReadOnlySet ITargetedFields.Relationships => Relationships; + IReadOnlySet ITargetedFields.Attributes => Attributes.AsReadOnly(); + IReadOnlySet ITargetedFields.Relationships => Relationships.AsReadOnly(); public HashSet Attributes { get; } = []; public HashSet Relationships { get; } = []; @@ -16,6 +16,8 @@ public sealed class TargetedFields : ITargetedFields /// public void CopyFrom(ITargetedFields other) { + ArgumentNullException.ThrowIfNull(other); + Clear(); Attributes.UnionWith(other.Attributes); diff --git a/src/JsonApiDotNetCore/Serialization/JsonConverters/JsonObjectConverter.cs b/src/JsonApiDotNetCore/Serialization/JsonConverters/JsonObjectConverter.cs index 32e4351e12..054fc28e55 100644 --- a/src/JsonApiDotNetCore/Serialization/JsonConverters/JsonObjectConverter.cs +++ b/src/JsonApiDotNetCore/Serialization/JsonConverters/JsonObjectConverter.cs @@ -7,6 +7,8 @@ public abstract class JsonObjectConverter : JsonConverter { protected static TValue? ReadSubTree(ref Utf8JsonReader reader, JsonSerializerOptions options) { + ArgumentNullException.ThrowIfNull(options); + if (typeof(TValue) != typeof(object) && options.GetConverter(typeof(TValue)) is JsonConverter converter) { return converter.Read(ref reader, typeof(TValue), options); @@ -17,6 +19,8 @@ public abstract class JsonObjectConverter : JsonConverter protected static void WriteSubTree(Utf8JsonWriter writer, TValue value, JsonSerializerOptions options) { + ArgumentNullException.ThrowIfNull(options); + if (typeof(TValue) != typeof(object) && options.GetConverter(typeof(TValue)) is JsonConverter converter) { converter.Write(writer, value, options); diff --git a/src/JsonApiDotNetCore/Serialization/JsonConverters/ResourceObjectConverter.cs b/src/JsonApiDotNetCore/Serialization/JsonConverters/ResourceObjectConverter.cs index 25218b1ba9..d20bdd5f0d 100644 --- a/src/JsonApiDotNetCore/Serialization/JsonConverters/ResourceObjectConverter.cs +++ b/src/JsonApiDotNetCore/Serialization/JsonConverters/ResourceObjectConverter.cs @@ -1,7 +1,10 @@ +using System.Diagnostics.CodeAnalysis; using System.Reflection; +using System.Runtime.ExceptionServices; using System.Text.Json; using JetBrains.Annotations; using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Errors; using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; using JsonApiDotNetCore.Serialization.Objects; @@ -13,7 +16,7 @@ namespace JsonApiDotNetCore.Serialization.JsonConverters; /// Converts to/from JSON. /// [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] -public sealed class ResourceObjectConverter : JsonObjectConverter +public class ResourceObjectConverter : JsonObjectConverter { private static readonly JsonEncodedText TypeText = JsonEncodedText.Encode("type"); private static readonly JsonEncodedText IdText = JsonEncodedText.Encode("id"); @@ -27,7 +30,7 @@ public sealed class ResourceObjectConverter : JsonObjectConverter>(ref reader, options); + if (resourceType != null) + { + resourceObject.Relationships = ReadRelationships(ref reader, options, resourceType); + } + else + { + reader.Skip(); + } + break; } case "links": @@ -127,27 +138,27 @@ public override ResourceObject Read(ref Utf8JsonReader reader, Type typeToConver throw GetEndOfStreamError(); } - private static string? PeekType(ref Utf8JsonReader reader) + private static string? PeekType(Utf8JsonReader reader) { - // https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to?pivots=dotnet-5-0#an-alternative-way-to-do-polymorphic-deserialization - Utf8JsonReader readerClone = reader; + // This method receives a clone of the reader (which is a struct, and there's no ref modifier on the parameter), + // so advancing here doesn't affect the reader position of the caller. - while (readerClone.Read()) + while (reader.Read()) { - if (readerClone.TokenType == JsonTokenType.PropertyName) + if (reader.TokenType == JsonTokenType.PropertyName) { - string? propertyName = readerClone.GetString(); - readerClone.Read(); + string? propertyName = reader.GetString(); + reader.Read(); switch (propertyName) { case "type": { - return readerClone.GetString(); + return reader.GetString(); } default: { - readerClone.Skip(); + reader.Skip(); break; } } @@ -157,7 +168,7 @@ public override ResourceObject Read(ref Utf8JsonReader reader, Type typeToConver return null; } - private static IDictionary ReadAttributes(ref Utf8JsonReader reader, JsonSerializerOptions options, ResourceType resourceType) + private Dictionary ReadAttributes(ref Utf8JsonReader reader, JsonSerializerOptions options, ResourceType resourceType) { var attributes = new Dictionary(); @@ -174,6 +185,18 @@ public override ResourceObject Read(ref Utf8JsonReader reader, Type typeToConver string attributeName = reader.GetString() ?? string.Empty; reader.Read(); + int extensionSeparatorIndex = attributeName.IndexOf(':'); + + if (extensionSeparatorIndex != -1) + { + string extensionNamespace = attributeName[..extensionSeparatorIndex]; + string extensionName = attributeName[(extensionSeparatorIndex + 1)..]; + + ValidateExtensionInAttributes(extensionNamespace, extensionName, resourceType, reader); + reader.Skip(); + continue; + } + AttrAttribute? attribute = resourceType.FindAttributeByPublicName(attributeName); PropertyInfo? property = attribute?.Property; @@ -203,14 +226,61 @@ public override ResourceObject Read(ref Utf8JsonReader reader, Type typeToConver } } - attributes.Add(attributeName, attributeValue); + attributes[attributeName] = attributeValue; } else { - attributes.Add(attributeName, null); + attributes[attributeName] = null; + reader.Skip(); + } + + break; + } + } + } + + throw GetEndOfStreamError(); + } + + // Currently exposed for internal use only, so we don't need a breaking change when adding support for multiple extensions. + // ReSharper disable once UnusedParameter.Global + private protected virtual void ValidateExtensionInAttributes(string extensionNamespace, string extensionName, ResourceType resourceType, + Utf8JsonReader reader) + { + throw new JsonException($"Unsupported usage of JSON:API extension '{extensionNamespace}' in attributes."); + } + + private Dictionary ReadRelationships(ref Utf8JsonReader reader, JsonSerializerOptions options, ResourceType resourceType) + { + var relationships = new Dictionary(); + + while (reader.Read()) + { + switch (reader.TokenType) + { + case JsonTokenType.EndObject: + { + return relationships; + } + case JsonTokenType.PropertyName: + { + string relationshipName = reader.GetString() ?? string.Empty; + reader.Read(); + + int extensionSeparatorIndex = relationshipName.IndexOf(':'); + + if (extensionSeparatorIndex != -1) + { + string extensionNamespace = relationshipName[..extensionSeparatorIndex]; + string extensionName = relationshipName[(extensionSeparatorIndex + 1)..]; + + ValidateExtensionInRelationships(extensionNamespace, extensionName, resourceType, reader); reader.Skip(); + continue; } + var relationshipObject = ReadSubTree(ref reader, options); + relationships[relationshipName] = relationshipObject; break; } } @@ -219,11 +289,22 @@ public override ResourceObject Read(ref Utf8JsonReader reader, Type typeToConver throw GetEndOfStreamError(); } + // Currently exposed for internal use only, so we don't need a breaking change when adding support for multiple extensions. + // ReSharper disable once UnusedParameter.Global + private protected virtual void ValidateExtensionInRelationships(string extensionNamespace, string extensionName, ResourceType resourceType, + Utf8JsonReader reader) + { + throw new JsonException($"Unsupported usage of JSON:API extension '{extensionNamespace}' in relationships."); + } + /// /// Ensures that attribute values are not wrapped in s. /// public override void Write(Utf8JsonWriter writer, ResourceObject value, JsonSerializerOptions options) { + ArgumentNullException.ThrowIfNull(writer); + ArgumentNullException.ThrowIfNull(value); + writer.WriteStartObject(); writer.WriteString(TypeText, value.Type); @@ -241,13 +322,33 @@ public override void Write(Utf8JsonWriter writer, ResourceObject value, JsonSeri if (!value.Attributes.IsNullOrEmpty()) { writer.WritePropertyName(AttributesText); - WriteSubTree(writer, value.Attributes, options); + writer.WriteStartObject(); + + WriteExtensionInAttributes(writer, value); + + foreach ((string attributeName, object? attributeValue) in value.Attributes) + { + writer.WritePropertyName(attributeName); + WriteSubTree(writer, attributeValue, options); + } + + writer.WriteEndObject(); } if (!value.Relationships.IsNullOrEmpty()) { writer.WritePropertyName(RelationshipsText); - WriteSubTree(writer, value.Relationships, options); + writer.WriteStartObject(); + + WriteExtensionInRelationships(writer, value); + + foreach ((string relationshipName, RelationshipObject? relationshipValue) in value.Relationships) + { + writer.WritePropertyName(relationshipName); + WriteSubTree(writer, relationshipValue, options); + } + + writer.WriteEndObject(); } if (value.Links != null && value.Links.HasValue()) @@ -264,4 +365,32 @@ public override void Write(Utf8JsonWriter writer, ResourceObject value, JsonSeri writer.WriteEndObject(); } + + // Currently exposed for internal use only, so we don't need a breaking change when adding support for multiple extensions. + private protected virtual void WriteExtensionInAttributes(Utf8JsonWriter writer, ResourceObject value) + { + } + + // Currently exposed for internal use only, so we don't need a breaking change when adding support for multiple extensions. + private protected virtual void WriteExtensionInRelationships(Utf8JsonWriter writer, ResourceObject value) + { + } + + /// + /// Throws a in such a way that can reconstruct the source pointer. + /// + /// + /// The to throw, which may contain a relative source pointer. + /// + [DoesNotReturn] + [ContractAnnotation("=> halt")] + private protected static void CapturedThrow(JsonApiException exception) + { + ExceptionDispatchInfo.SetCurrentStackTrace(exception); + + throw new NotSupportedException(null, exception) + { + Source = "System.Text.Json.Rethrowable" + }; + } } diff --git a/src/JsonApiDotNetCore/Serialization/JsonConverters/SingleOrManyDataConverterFactory.cs b/src/JsonApiDotNetCore/Serialization/JsonConverters/SingleOrManyDataConverterFactory.cs index 457f5082ef..81ae41a380 100644 --- a/src/JsonApiDotNetCore/Serialization/JsonConverters/SingleOrManyDataConverterFactory.cs +++ b/src/JsonApiDotNetCore/Serialization/JsonConverters/SingleOrManyDataConverterFactory.cs @@ -14,12 +14,16 @@ public sealed class SingleOrManyDataConverterFactory : JsonConverterFactory /// public override bool CanConvert(Type typeToConvert) { + ArgumentNullException.ThrowIfNull(typeToConvert); + return typeToConvert.IsGenericType && typeToConvert.GetGenericTypeDefinition() == typeof(SingleOrManyData<>); } /// public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { + ArgumentNullException.ThrowIfNull(typeToConvert); + Type objectType = typeToConvert.GetGenericArguments()[0]; Type converterType = typeof(SingleOrManyDataConverter<>).MakeGenericType(objectType); @@ -31,7 +35,7 @@ private sealed class SingleOrManyDataConverter : JsonObjectConverter Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - var objects = new List(); + List objects = []; bool isManyData = false; bool hasCompletedToMany = false; diff --git a/src/JsonApiDotNetCore/Serialization/JsonConverters/WriteOnlyDocumentConverter.cs b/src/JsonApiDotNetCore/Serialization/JsonConverters/WriteOnlyDocumentConverter.cs index a8f3e7f81e..f459b49c9b 100644 --- a/src/JsonApiDotNetCore/Serialization/JsonConverters/WriteOnlyDocumentConverter.cs +++ b/src/JsonApiDotNetCore/Serialization/JsonConverters/WriteOnlyDocumentConverter.cs @@ -32,6 +32,9 @@ public override Document Read(ref Utf8JsonReader reader, Type typeToConvert, Jso /// public override void Write(Utf8JsonWriter writer, Document value, JsonSerializerOptions options) { + ArgumentNullException.ThrowIfNull(writer); + ArgumentNullException.ThrowIfNull(value); + writer.WriteStartObject(); if (value.JsonApi != null) diff --git a/src/JsonApiDotNetCore/Serialization/JsonConverters/WriteOnlyRelationshipObjectConverter.cs b/src/JsonApiDotNetCore/Serialization/JsonConverters/WriteOnlyRelationshipObjectConverter.cs index e34fc7636f..db6b7dc686 100644 --- a/src/JsonApiDotNetCore/Serialization/JsonConverters/WriteOnlyRelationshipObjectConverter.cs +++ b/src/JsonApiDotNetCore/Serialization/JsonConverters/WriteOnlyRelationshipObjectConverter.cs @@ -27,6 +27,9 @@ public override RelationshipObject Read(ref Utf8JsonReader reader, Type typeToCo /// public override void Write(Utf8JsonWriter writer, RelationshipObject value, JsonSerializerOptions options) { + ArgumentNullException.ThrowIfNull(writer); + ArgumentNullException.ThrowIfNull(value); + writer.WriteStartObject(); if (value.Links != null && value.Links.HasValue()) diff --git a/src/JsonApiDotNetCore/Serialization/Objects/JsonApiObject.cs b/src/JsonApiDotNetCore/Serialization/Objects/JsonapiObject.cs similarity index 100% rename from src/JsonApiDotNetCore/Serialization/Objects/JsonApiObject.cs rename to src/JsonApiDotNetCore/Serialization/Objects/JsonapiObject.cs diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/AtomicOperationObjectAdapter.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/AtomicOperationObjectAdapter.cs index 795030598c..4339cf6c48 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/AtomicOperationObjectAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/AtomicOperationObjectAdapter.cs @@ -17,10 +17,10 @@ public sealed class AtomicOperationObjectAdapter : IAtomicOperationObjectAdapter public AtomicOperationObjectAdapter(IJsonApiOptions options, IAtomicReferenceAdapter atomicReferenceAdapter, IResourceDataInOperationsRequestAdapter resourceDataInOperationsRequestAdapter, IRelationshipDataAdapter relationshipDataAdapter) { - ArgumentGuard.NotNull(options); - ArgumentGuard.NotNull(atomicReferenceAdapter); - ArgumentGuard.NotNull(resourceDataInOperationsRequestAdapter); - ArgumentGuard.NotNull(relationshipDataAdapter); + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(atomicReferenceAdapter); + ArgumentNullException.ThrowIfNull(resourceDataInOperationsRequestAdapter); + ArgumentNullException.ThrowIfNull(relationshipDataAdapter); _options = options; _atomicReferenceAdapter = atomicReferenceAdapter; @@ -31,6 +31,9 @@ public AtomicOperationObjectAdapter(IJsonApiOptions options, IAtomicReferenceAda /// public OperationContainer Convert(AtomicOperationObject atomicOperationObject, RequestAdapterState state) { + ArgumentNullException.ThrowIfNull(atomicOperationObject); + ArgumentNullException.ThrowIfNull(state); + AssertNoHref(atomicOperationObject, state); WriteOperationKind writeOperation = ConvertOperationCode(atomicOperationObject, state); diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/AtomicReferenceAdapter.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/AtomicReferenceAdapter.cs index 8e682439aa..0dc72a08fa 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/AtomicReferenceAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/AtomicReferenceAdapter.cs @@ -14,9 +14,9 @@ public sealed class AtomicReferenceAdapter(IResourceGraph resourceGraph, IResour /// public AtomicReferenceResult Convert(AtomicReference atomicReference, ResourceIdentityRequirements requirements, RequestAdapterState state) { - ArgumentGuard.NotNull(atomicReference); - ArgumentGuard.NotNull(requirements); - ArgumentGuard.NotNull(state); + ArgumentNullException.ThrowIfNull(atomicReference); + ArgumentNullException.ThrowIfNull(requirements); + ArgumentNullException.ThrowIfNull(state); using IDisposable _ = state.Position.PushElement("ref"); (IIdentifiable resource, ResourceType resourceType) = ConvertResourceIdentity(atomicReference, requirements, state); diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/AtomicReferenceResult.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/AtomicReferenceResult.cs index a15ecd8e0c..367d7ec2ea 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/AtomicReferenceResult.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/AtomicReferenceResult.cs @@ -17,8 +17,8 @@ public sealed class AtomicReferenceResult public AtomicReferenceResult(IIdentifiable resource, ResourceType resourceType, RelationshipAttribute? relationship) { - ArgumentGuard.NotNull(resource); - ArgumentGuard.NotNull(resourceType); + ArgumentNullException.ThrowIfNull(resource); + ArgumentNullException.ThrowIfNull(resourceType); Resource = resource; ResourceType = resourceType; diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/BaseAdapter.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/BaseAdapter.cs index fb1111bea1..8969d28fd7 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/BaseAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/BaseAdapter.cs @@ -13,6 +13,8 @@ public abstract class BaseAdapter protected static void AssertHasData(SingleOrManyData data, RequestAdapterState state) where T : ResourceIdentifierObject, new() { + ArgumentNullException.ThrowIfNull(state); + if (!data.IsAssigned) { throw new ModelConversionException(state.Position, "The 'data' element is required.", null); @@ -23,6 +25,8 @@ protected static void AssertHasData(SingleOrManyData data, RequestAdapterS protected static void AssertDataHasSingleValue(SingleOrManyData data, bool allowNull, RequestAdapterState state) where T : ResourceIdentifierObject, new() { + ArgumentNullException.ThrowIfNull(state); + if (data.SingleValue == null) { if (!allowNull) @@ -46,6 +50,8 @@ protected static void AssertDataHasSingleValue(SingleOrManyData data, bool protected static void AssertDataHasManyValue(SingleOrManyData data, RequestAdapterState state) where T : ResourceIdentifierObject, new() { + ArgumentNullException.ThrowIfNull(state); + if (data.ManyValue == null) { throw new ModelConversionException(state.Position, @@ -56,6 +62,8 @@ protected static void AssertDataHasManyValue(SingleOrManyData data, Reques protected static void AssertObjectIsNotNull([SysNotNull] T? value, RequestAdapterState state) where T : class { + ArgumentNullException.ThrowIfNull(state); + if (value is null) { throw new ModelConversionException(state.Position, "Expected an object, instead of 'null'.", null); diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/DocumentAdapter.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/DocumentAdapter.cs index ec9842b271..f5b514b202 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/DocumentAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/DocumentAdapter.cs @@ -16,10 +16,10 @@ public DocumentAdapter(IJsonApiRequest request, ITargetedFields targetedFields, IDocumentInResourceOrRelationshipRequestAdapter documentInResourceOrRelationshipRequestAdapter, IDocumentInOperationsRequestAdapter documentInOperationsRequestAdapter) { - ArgumentGuard.NotNull(request); - ArgumentGuard.NotNull(targetedFields); - ArgumentGuard.NotNull(documentInResourceOrRelationshipRequestAdapter); - ArgumentGuard.NotNull(documentInOperationsRequestAdapter); + ArgumentNullException.ThrowIfNull(request); + ArgumentNullException.ThrowIfNull(targetedFields); + ArgumentNullException.ThrowIfNull(documentInResourceOrRelationshipRequestAdapter); + ArgumentNullException.ThrowIfNull(documentInOperationsRequestAdapter); _request = request; _targetedFields = targetedFields; @@ -30,7 +30,7 @@ public DocumentAdapter(IJsonApiRequest request, ITargetedFields targetedFields, /// public object? Convert(Document document) { - ArgumentGuard.NotNull(document); + ArgumentNullException.ThrowIfNull(document); using var adapterState = new RequestAdapterState(_request, _targetedFields); diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/DocumentInOperationsRequestAdapter.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/DocumentInOperationsRequestAdapter.cs index 2a272c4cfd..bb75927c92 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/DocumentInOperationsRequestAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/DocumentInOperationsRequestAdapter.cs @@ -13,17 +13,19 @@ public sealed class DocumentInOperationsRequestAdapter : BaseAdapter, IDocumentI public DocumentInOperationsRequestAdapter(IJsonApiOptions options, IAtomicOperationObjectAdapter atomicOperationObjectAdapter) { - ArgumentGuard.NotNull(options); - ArgumentGuard.NotNull(atomicOperationObjectAdapter); + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(atomicOperationObjectAdapter); _options = options; _atomicOperationObjectAdapter = atomicOperationObjectAdapter; } /// - public IReadOnlyList Convert(Document document, RequestAdapterState state) + public IList Convert(Document document, RequestAdapterState state) { - ArgumentGuard.NotNull(state); + ArgumentNullException.ThrowIfNull(document); + ArgumentNullException.ThrowIfNull(state); + AssertHasOperations(document.Operations, state); using IDisposable _ = state.Position.PushElement("atomic:operations"); @@ -40,19 +42,18 @@ private static void AssertHasOperations([NotNull] IEnumerable atomicOperationObjects, RequestAdapterState state) + private void AssertMaxOperationsNotExceeded(IList atomicOperationObjects, RequestAdapterState state) { if (atomicOperationObjects.Count > _options.MaximumOperationsPerRequest) { throw new ModelConversionException(state.Position, "Too many operations in request.", - $"The number of operations in this request ({atomicOperationObjects.Count}) is higher " + - $"than the maximum of {_options.MaximumOperationsPerRequest}."); + $"The number of operations in this request ({atomicOperationObjects.Count}) is higher than the maximum of {_options.MaximumOperationsPerRequest}."); } } - private IReadOnlyList ConvertOperations(IEnumerable atomicOperationObjects, RequestAdapterState state) + private List ConvertOperations(IEnumerable atomicOperationObjects, RequestAdapterState state) { - var operations = new List(); + List operations = []; int operationIndex = 0; foreach (AtomicOperationObject? atomicOperationObject in atomicOperationObjects) diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/DocumentInResourceOrRelationshipRequestAdapter.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/DocumentInResourceOrRelationshipRequestAdapter.cs index 8a031b692e..48b0c2c5f6 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/DocumentInResourceOrRelationshipRequestAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/DocumentInResourceOrRelationshipRequestAdapter.cs @@ -15,9 +15,9 @@ public sealed class DocumentInResourceOrRelationshipRequestAdapter : IDocumentIn public DocumentInResourceOrRelationshipRequestAdapter(IJsonApiOptions options, IResourceDataAdapter resourceDataAdapter, IRelationshipDataAdapter relationshipDataAdapter) { - ArgumentGuard.NotNull(options); - ArgumentGuard.NotNull(resourceDataAdapter); - ArgumentGuard.NotNull(relationshipDataAdapter); + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(resourceDataAdapter); + ArgumentNullException.ThrowIfNull(relationshipDataAdapter); _options = options; _resourceDataAdapter = resourceDataAdapter; @@ -27,6 +27,9 @@ public DocumentInResourceOrRelationshipRequestAdapter(IJsonApiOptions options, I /// public object? Convert(Document document, RequestAdapterState state) { + ArgumentNullException.ThrowIfNull(document); + ArgumentNullException.ThrowIfNull(state); + state.WritableTargetedFields = new TargetedFields(); switch (state.Request.WriteOperation) diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/IDocumentInOperationsRequestAdapter.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/IDocumentInOperationsRequestAdapter.cs index b4e929cba3..7f6a6935cf 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/IDocumentInOperationsRequestAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/IDocumentInOperationsRequestAdapter.cs @@ -11,5 +11,7 @@ public interface IDocumentInOperationsRequestAdapter /// /// Validates and converts the specified . /// - IReadOnlyList Convert(Document document, RequestAdapterState state); +#pragma warning disable AV1130 // Return type in method signature should be an interface to an unchangeable collection + IList Convert(Document document, RequestAdapterState state); +#pragma warning restore AV1130 // Return type in method signature should be an interface to an unchangeable collection } diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/RelationshipDataAdapter.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/RelationshipDataAdapter.cs index 0e7f292394..a488e727af 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/RelationshipDataAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/RelationshipDataAdapter.cs @@ -9,13 +9,11 @@ namespace JsonApiDotNetCore.Serialization.Request.Adapters; /// public sealed class RelationshipDataAdapter : BaseAdapter, IRelationshipDataAdapter { - private static readonly CollectionConverter CollectionConverter = new(); - private readonly IResourceIdentifierObjectAdapter _resourceIdentifierObjectAdapter; public RelationshipDataAdapter(IResourceIdentifierObjectAdapter resourceIdentifierObjectAdapter) { - ArgumentGuard.NotNull(resourceIdentifierObjectAdapter); + ArgumentNullException.ThrowIfNull(resourceIdentifierObjectAdapter); _resourceIdentifierObjectAdapter = resourceIdentifierObjectAdapter; } @@ -62,8 +60,8 @@ private static SingleOrManyData ToIdentifierData(Singl public object? Convert(SingleOrManyData data, RelationshipAttribute relationship, bool useToManyElementType, RequestAdapterState state) { - ArgumentGuard.NotNull(relationship); - ArgumentGuard.NotNull(state); + ArgumentNullException.ThrowIfNull(relationship); + ArgumentNullException.ThrowIfNull(state); AssertHasData(data, state); using IDisposable _ = state.Position.PushElement("data"); @@ -95,7 +93,7 @@ private IEnumerable ConvertToManyRelationshipData(SingleOrManyData(); + List rightResources = []; foreach (ResourceIdentifierObject resourceIdentifierObject in data.ManyValue!) { @@ -109,7 +107,7 @@ private IEnumerable ConvertToManyRelationshipData(SingleOrManyData(IdentifiableComparer.Instance); diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/RequestAdapterPosition.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/RequestAdapterPosition.cs index 3b114f61f4..da3ef481b5 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/RequestAdapterPosition.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/RequestAdapterPosition.cs @@ -1,6 +1,8 @@ using System.Text; using JetBrains.Annotations; +#pragma warning disable CA1001 // Types that own disposable fields should be disposable + namespace JsonApiDotNetCore.Serialization.Request.Adapters; /// @@ -19,7 +21,7 @@ public RequestAdapterPosition() public IDisposable PushElement(string name) { - ArgumentGuard.NotNullNorEmpty(name); + ArgumentException.ThrowIfNullOrWhiteSpace(name); _stack.Push($"/{name}"); return _disposable; @@ -33,7 +35,7 @@ public IDisposable PushArrayIndex(int index) public string? ToSourcePointer() { - if (!_stack.Any()) + if (_stack.Count == 0) { return null; } @@ -41,7 +43,7 @@ public IDisposable PushArrayIndex(int index) var builder = new StringBuilder(); var clone = new Stack(_stack); - while (clone.Any()) + while (clone.Count > 0) { string element = clone.Pop(); builder.Append(element); diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/RequestAdapterState.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/RequestAdapterState.cs index c7d40e1794..089bd48bdf 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/RequestAdapterState.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/RequestAdapterState.cs @@ -11,7 +11,7 @@ namespace JsonApiDotNetCore.Serialization.Request.Adapters; [PublicAPI] public sealed class RequestAdapterState : IDisposable { - private readonly IDisposable? _backupRequestState; + private readonly RevertRequestStateOnDispose? _backupRequestState; public IJsonApiRequest InjectableRequest { get; } public ITargetedFields InjectableTargetedFields { get; } @@ -24,8 +24,8 @@ public sealed class RequestAdapterState : IDisposable public RequestAdapterState(IJsonApiRequest request, ITargetedFields targetedFields) { - ArgumentGuard.NotNull(request); - ArgumentGuard.NotNull(targetedFields); + ArgumentNullException.ThrowIfNull(request); + ArgumentNullException.ThrowIfNull(targetedFields); InjectableRequest = request; InjectableTargetedFields = targetedFields; diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceDataAdapter.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceDataAdapter.cs index ffe971f42f..91f745327d 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceDataAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceDataAdapter.cs @@ -12,8 +12,8 @@ public class ResourceDataAdapter : BaseAdapter, IResourceDataAdapter public ResourceDataAdapter(IResourceDefinitionAccessor resourceDefinitionAccessor, IResourceObjectAdapter resourceObjectAdapter) { - ArgumentGuard.NotNull(resourceDefinitionAccessor); - ArgumentGuard.NotNull(resourceObjectAdapter); + ArgumentNullException.ThrowIfNull(resourceDefinitionAccessor); + ArgumentNullException.ThrowIfNull(resourceObjectAdapter); _resourceDefinitionAccessor = resourceDefinitionAccessor; _resourceObjectAdapter = resourceObjectAdapter; @@ -22,8 +22,8 @@ public ResourceDataAdapter(IResourceDefinitionAccessor resourceDefinitionAccesso /// public IIdentifiable Convert(SingleOrManyData data, ResourceIdentityRequirements requirements, RequestAdapterState state) { - ArgumentGuard.NotNull(requirements); - ArgumentGuard.NotNull(state); + ArgumentNullException.ThrowIfNull(requirements); + ArgumentNullException.ThrowIfNull(state); AssertHasData(data, state); @@ -42,6 +42,9 @@ public IIdentifiable Convert(SingleOrManyData data, ResourceIden protected virtual (IIdentifiable resource, ResourceType resourceType) ConvertResourceObject(SingleOrManyData data, ResourceIdentityRequirements requirements, RequestAdapterState state) { + ArgumentNullException.ThrowIfNull(requirements); + ArgumentNullException.ThrowIfNull(state); + return _resourceObjectAdapter.Convert(data.SingleValue!, requirements, state); } } diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceDataInOperationsRequestAdapter.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceDataInOperationsRequestAdapter.cs index 7c299b0b5e..30deb3c9ba 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceDataInOperationsRequestAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceDataInOperationsRequestAdapter.cs @@ -11,6 +11,9 @@ public sealed class ResourceDataInOperationsRequestAdapter(IResourceDefinitionAc protected override (IIdentifiable resource, ResourceType resourceType) ConvertResourceObject(SingleOrManyData data, ResourceIdentityRequirements requirements, RequestAdapterState state) { + ArgumentNullException.ThrowIfNull(requirements); + ArgumentNullException.ThrowIfNull(state); + // This override ensures that we enrich IJsonApiRequest before calling into IResourceDefinition, so it is ready for consumption there. (IIdentifiable resource, ResourceType resourceType) = base.ConvertResourceObject(data, requirements, state); diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceIdentifierObjectAdapter.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceIdentifierObjectAdapter.cs index bc9d380388..05e2bcdafb 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceIdentifierObjectAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceIdentifierObjectAdapter.cs @@ -11,9 +11,9 @@ public sealed class ResourceIdentifierObjectAdapter(IResourceGraph resourceGraph /// public IIdentifiable Convert(ResourceIdentifierObject resourceIdentifierObject, ResourceIdentityRequirements requirements, RequestAdapterState state) { - ArgumentGuard.NotNull(resourceIdentifierObject); - ArgumentGuard.NotNull(requirements); - ArgumentGuard.NotNull(state); + ArgumentNullException.ThrowIfNull(resourceIdentifierObject); + ArgumentNullException.ThrowIfNull(requirements); + ArgumentNullException.ThrowIfNull(state); (IIdentifiable resource, _) = ConvertResourceIdentity(resourceIdentifierObject, requirements, state); return resource; diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceIdentityAdapter.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceIdentityAdapter.cs index 5e25dba0f7..d0def4e9cd 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceIdentityAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceIdentityAdapter.cs @@ -18,8 +18,8 @@ public abstract class ResourceIdentityAdapter : BaseAdapter protected ResourceIdentityAdapter(IResourceGraph resourceGraph, IResourceFactory resourceFactory) { - ArgumentGuard.NotNull(resourceGraph); - ArgumentGuard.NotNull(resourceFactory); + ArgumentNullException.ThrowIfNull(resourceGraph); + ArgumentNullException.ThrowIfNull(resourceFactory); _resourceGraph = resourceGraph; _resourceFactory = resourceFactory; @@ -28,9 +28,9 @@ protected ResourceIdentityAdapter(IResourceGraph resourceGraph, IResourceFactory protected (IIdentifiable resource, ResourceType resourceType) ConvertResourceIdentity(ResourceIdentity identity, ResourceIdentityRequirements requirements, RequestAdapterState state) { - ArgumentGuard.NotNull(identity); - ArgumentGuard.NotNull(requirements); - ArgumentGuard.NotNull(state); + ArgumentNullException.ThrowIfNull(identity); + ArgumentNullException.ThrowIfNull(requirements); + ArgumentNullException.ThrowIfNull(state); ResourceType resourceType = ResolveType(identity, requirements, state); IIdentifiable resource = CreateResource(identity, requirements, resourceType, state); @@ -116,6 +116,7 @@ private IIdentifiable CreateResource(ResourceIdentity identity, ResourceIdentity AssertHasNoId(identity, state); } + AssertNoBrokenId(identity, resourceType.IdentityClrType, state); AssertSameIdValue(identity, requirements.IdValue, state); AssertSameLidValue(identity, requirements.LidValue, state); @@ -177,6 +178,25 @@ private static void AssertHasNoId(ResourceIdentity identity, RequestAdapterState } } + private static void AssertNoBrokenId(ResourceIdentity identity, Type resourceIdClrType, RequestAdapterState state) + { + if (identity.Id != null) + { + if (resourceIdClrType == typeof(string)) + { + // Empty and whitespace strings are valid when TId is string. + return; + } + + string? defaultIdValue = RuntimeTypeConverter.GetDefaultValue(resourceIdClrType)?.ToString(); + + if (string.IsNullOrWhiteSpace(identity.Id) || identity.Id == defaultIdValue) + { + throw new ModelConversionException(state.Position, "The 'id' element is invalid.", null); + } + } + } + private static void AssertSameIdValue(ResourceIdentity identity, string? expected, RequestAdapterState state) { if (expected != null && identity.Id != expected) @@ -218,6 +238,10 @@ private void AssignStringId(ResourceIdentity identity, IIdentifiable resource, R protected static void AssertIsKnownRelationship([NotNull] RelationshipAttribute? relationship, string relationshipName, ResourceType resourceType, RequestAdapterState state) { + ArgumentNullException.ThrowIfNull(relationshipName); + ArgumentNullException.ThrowIfNull(resourceType); + ArgumentNullException.ThrowIfNull(state); + if (relationship == null) { throw new ModelConversionException(state.Position, "Unknown relationship found.", @@ -227,6 +251,9 @@ protected static void AssertIsKnownRelationship([NotNull] RelationshipAttribute? protected internal static void AssertToManyInAddOrRemoveRelationship(RelationshipAttribute relationship, RequestAdapterState state) { + ArgumentNullException.ThrowIfNull(relationship); + ArgumentNullException.ThrowIfNull(state); + bool requireToManyRelationship = state.Request.WriteOperation is WriteOperationKind.AddToRelationship or WriteOperationKind.RemoveFromRelationship; if (requireToManyRelationship && relationship is not HasManyAttribute) diff --git a/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceObjectAdapter.cs b/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceObjectAdapter.cs index 1b85b35336..5f9b4dd05c 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceObjectAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/Adapters/ResourceObjectAdapter.cs @@ -17,8 +17,8 @@ public ResourceObjectAdapter(IResourceGraph resourceGraph, IResourceFactory reso IRelationshipDataAdapter relationshipDataAdapter) : base(resourceGraph, resourceFactory) { - ArgumentGuard.NotNull(options); - ArgumentGuard.NotNull(relationshipDataAdapter); + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(relationshipDataAdapter); _options = options; _relationshipDataAdapter = relationshipDataAdapter; @@ -28,9 +28,9 @@ public ResourceObjectAdapter(IResourceGraph resourceGraph, IResourceFactory reso public (IIdentifiable resource, ResourceType resourceType) Convert(ResourceObject resourceObject, ResourceIdentityRequirements requirements, RequestAdapterState state) { - ArgumentGuard.NotNull(resourceObject); - ArgumentGuard.NotNull(requirements); - ArgumentGuard.NotNull(state); + ArgumentNullException.ThrowIfNull(resourceObject); + ArgumentNullException.ThrowIfNull(requirements); + ArgumentNullException.ThrowIfNull(state); (IIdentifiable resource, ResourceType resourceType) = ConvertResourceIdentity(resourceObject, requirements, state); diff --git a/src/JsonApiDotNetCore/Serialization/Request/JsonApiReader.cs b/src/JsonApiDotNetCore/Serialization/Request/JsonApiReader.cs index 4bd3741b7e..9c0139d949 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/JsonApiReader.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/JsonApiReader.cs @@ -5,7 +5,6 @@ using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Diagnostics; using JsonApiDotNetCore.Errors; -using JsonApiDotNetCore.Middleware; using JsonApiDotNetCore.Serialization.Objects; using JsonApiDotNetCore.Serialization.Request.Adapters; using Microsoft.AspNetCore.Http; @@ -17,32 +16,36 @@ namespace JsonApiDotNetCore.Serialization.Request; /// -public sealed class JsonApiReader : IJsonApiReader +public sealed partial class JsonApiReader : IJsonApiReader { private readonly IJsonApiOptions _options; private readonly IDocumentAdapter _documentAdapter; - private readonly TraceLogWriter _traceWriter; + private readonly ILogger _logger; - public JsonApiReader(IJsonApiOptions options, IDocumentAdapter documentAdapter, ILoggerFactory loggerFactory) + public JsonApiReader(IJsonApiOptions options, IDocumentAdapter documentAdapter, ILogger logger) { - ArgumentGuard.NotNull(options); - ArgumentGuard.NotNull(documentAdapter); - ArgumentGuard.NotNull(loggerFactory); + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(documentAdapter); + ArgumentNullException.ThrowIfNull(logger); _options = options; _documentAdapter = documentAdapter; - _traceWriter = new TraceLogWriter(loggerFactory); + _logger = logger; } /// public async Task ReadAsync(HttpRequest httpRequest) { - ArgumentGuard.NotNull(httpRequest); + ArgumentNullException.ThrowIfNull(httpRequest); string requestBody = await ReceiveRequestBodyAsync(httpRequest); - string method = httpRequest.Method.Replace(Environment.NewLine, ""); - _traceWriter.LogMessage(() => $"Received {method} request at '{httpRequest.GetEncodedUrl()}' with body: <<{requestBody}>>"); + if (_logger.IsEnabled(LogLevel.Trace)) + { + string requestMethod = httpRequest.Method.Replace(Environment.NewLine, ""); + string requestUrl = httpRequest.GetEncodedUrl(); + LogRequest(requestMethod, requestUrl, requestBody); + } return GetModel(requestBody); } @@ -94,6 +97,10 @@ private Document DeserializeDocument(string requestBody) // https://github.com/dotnet/runtime/issues/50205#issuecomment-808401245 throw new InvalidRequestBodyException(_options.IncludeRequestBodyInErrors ? requestBody : null, null, exception.Message, null, null, exception); } + catch (NotSupportedException exception) when (exception.HasJsonApiException()) + { + throw exception.EnrichSourcePointer(); + } } private void AssertHasDocument([SysNotNull] Document? document, string requestBody) @@ -117,4 +124,8 @@ private void AssertHasDocument([SysNotNull] Document? document, string requestBo exception.SourcePointer, exception.StatusCode, exception); } } + + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, + Message = "Received {RequestMethod} request at '{RequestUrl}' with body: <<{RequestBody}>>")] + private partial void LogRequest(string requestMethod, string requestUrl, string requestBody); } diff --git a/src/JsonApiDotNetCore/Serialization/Request/JsonInvalidAttributeInfo.cs b/src/JsonApiDotNetCore/Serialization/Request/JsonInvalidAttributeInfo.cs index ed0afee834..4004e83de9 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/JsonInvalidAttributeInfo.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/JsonInvalidAttributeInfo.cs @@ -16,8 +16,8 @@ internal sealed class JsonInvalidAttributeInfo public JsonInvalidAttributeInfo(string attributeName, Type attributeType, string? jsonValue, JsonValueKind jsonType) { - ArgumentGuard.NotNullNorEmpty(attributeName); - ArgumentGuard.NotNull(attributeType); + ArgumentNullException.ThrowIfNull(attributeName); + ArgumentNullException.ThrowIfNull(attributeType); AttributeName = attributeName; AttributeType = attributeType; diff --git a/src/JsonApiDotNetCore/Serialization/Request/ModelConversionException.cs b/src/JsonApiDotNetCore/Serialization/Request/ModelConversionException.cs index cf2428129d..02db72573d 100644 --- a/src/JsonApiDotNetCore/Serialization/Request/ModelConversionException.cs +++ b/src/JsonApiDotNetCore/Serialization/Request/ModelConversionException.cs @@ -18,7 +18,7 @@ public sealed class ModelConversionException : Exception public ModelConversionException(RequestAdapterPosition position, string? genericMessage, string? specificMessage, HttpStatusCode? statusCode = null) : base(genericMessage) { - ArgumentGuard.NotNull(position); + ArgumentNullException.ThrowIfNull(position); GenericMessage = genericMessage; SpecificMessage = specificMessage; diff --git a/src/JsonApiDotNetCore/Serialization/Request/NotSupportedExceptionExtensions.cs b/src/JsonApiDotNetCore/Serialization/Request/NotSupportedExceptionExtensions.cs new file mode 100644 index 0000000000..bf05471f50 --- /dev/null +++ b/src/JsonApiDotNetCore/Serialization/Request/NotSupportedExceptionExtensions.cs @@ -0,0 +1,91 @@ +using System.Text.Json.Serialization; +using JsonApiDotNetCore.Errors; +using JsonApiDotNetCore.Serialization.Objects; + +namespace JsonApiDotNetCore.Serialization.Request; + +/// +/// A hacky approach to obtain the proper JSON:API source pointer from an exception thrown in a . +/// +/// +/// +/// This method relies on the behavior at +/// https://github.com/dotnet/runtime/blob/release/8.0/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.ReadCore.cs#L100, +/// which wraps a thrown and adds the JSON path to the outer exception message, based on internal reader state. +/// +/// +/// To take advantage of this, we expect a custom converter to throw a with a specially-crafted +/// and a nested containing a relative source pointer and a captured stack trace. Once +/// all of that happens, this class extracts the added JSON path from the outer exception message and converts it to a JSON:API pointer to enrich the +/// nested with. +/// +/// +internal static class NotSupportedExceptionExtensions +{ + private const string LeadingText = " Path: "; + private const string TrailingText = " | LineNumber: "; + + public static bool HasJsonApiException(this NotSupportedException exception) + { + return exception.InnerException is NotSupportedException { InnerException: JsonApiException }; + } + + public static JsonApiException EnrichSourcePointer(this NotSupportedException exception) + { + var jsonApiException = (JsonApiException)exception.InnerException!.InnerException!; + string? sourcePointer = GetSourcePointerFromMessage(exception.Message); + + if (sourcePointer != null) + { + foreach (ErrorObject error in jsonApiException.Errors) + { + if (error.Source == null) + { + error.Source = new ErrorSource + { + Pointer = sourcePointer + }; + } + else + { + error.Source.Pointer = $"{sourcePointer}/{error.Source.Pointer}"; + } + } + } + + return jsonApiException; + } + + private static string? GetSourcePointerFromMessage(string message) + { + string? jsonPath = ExtractJsonPathFromMessage(message); + return JsonPathToSourcePointer(jsonPath); + } + + private static string? ExtractJsonPathFromMessage(string message) + { + int startIndex = message.IndexOf(LeadingText, StringComparison.Ordinal); + + if (startIndex != -1) + { + int stopIndex = message.IndexOf(TrailingText, startIndex, StringComparison.Ordinal); + + if (stopIndex != -1) + { + return message.Substring(startIndex + LeadingText.Length, stopIndex - startIndex - LeadingText.Length); + } + } + + return null; + } + + private static string? JsonPathToSourcePointer(string? jsonPath) + { + if (jsonPath != null && jsonPath.StartsWith('$')) + { + return jsonPath[1..].Replace('.', '/'); + } + + return null; + } +} diff --git a/src/JsonApiDotNetCore/Serialization/Response/ETagGenerator.cs b/src/JsonApiDotNetCore/Serialization/Response/ETagGenerator.cs index d5aefb1fee..e88d9c17d4 100644 --- a/src/JsonApiDotNetCore/Serialization/Response/ETagGenerator.cs +++ b/src/JsonApiDotNetCore/Serialization/Response/ETagGenerator.cs @@ -9,7 +9,7 @@ internal sealed class ETagGenerator : IETagGenerator public ETagGenerator(IFingerprintGenerator fingerprintGenerator) { - ArgumentGuard.NotNull(fingerprintGenerator); + ArgumentNullException.ThrowIfNull(fingerprintGenerator); _fingerprintGenerator = fingerprintGenerator; } diff --git a/src/JsonApiDotNetCore/Serialization/Response/FingerprintGenerator.cs b/src/JsonApiDotNetCore/Serialization/Response/FingerprintGenerator.cs index 5baef6c086..61f3349df3 100644 --- a/src/JsonApiDotNetCore/Serialization/Response/FingerprintGenerator.cs +++ b/src/JsonApiDotNetCore/Serialization/Response/FingerprintGenerator.cs @@ -18,7 +18,7 @@ private static uint ToLookupEntry(int index) /// public string Generate(IEnumerable elements) { - ArgumentGuard.NotNull(elements); + ArgumentNullException.ThrowIfNull(elements); using var hasher = IncrementalHash.CreateHash(HashAlgorithmName.MD5); diff --git a/src/JsonApiDotNetCore/Serialization/Response/JsonApiWriter.cs b/src/JsonApiDotNetCore/Serialization/Response/JsonApiWriter.cs index 9a4e8869e7..67bb61213b 100644 --- a/src/JsonApiDotNetCore/Serialization/Response/JsonApiWriter.cs +++ b/src/JsonApiDotNetCore/Serialization/Response/JsonApiWriter.cs @@ -11,51 +11,43 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.WebUtilities; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Primitives; using Microsoft.Net.Http.Headers; namespace JsonApiDotNetCore.Serialization.Response; /// -public sealed class JsonApiWriter : IJsonApiWriter +public sealed partial class JsonApiWriter : IJsonApiWriter { - private static readonly MediaTypeHeaderValue OperationsMediaType = MediaTypeHeaderValue.Parse(HeaderConstants.AtomicOperationsMediaType); - private static readonly MediaTypeHeaderValue RelaxedOperationsMediaType = MediaTypeHeaderValue.Parse(HeaderConstants.RelaxedAtomicOperationsMediaType); - - private static readonly MediaTypeHeaderValue[] AllowedOperationsMediaTypes = - [ - OperationsMediaType, - RelaxedOperationsMediaType - ]; - private readonly IJsonApiRequest _request; private readonly IJsonApiOptions _options; private readonly IResponseModelAdapter _responseModelAdapter; private readonly IExceptionHandler _exceptionHandler; private readonly IETagGenerator _eTagGenerator; - private readonly TraceLogWriter _traceWriter; + private readonly ILogger _logger; public JsonApiWriter(IJsonApiRequest request, IJsonApiOptions options, IResponseModelAdapter responseModelAdapter, IExceptionHandler exceptionHandler, - IETagGenerator eTagGenerator, ILoggerFactory loggerFactory) + IETagGenerator eTagGenerator, ILogger logger) { - ArgumentGuard.NotNull(request); - ArgumentGuard.NotNull(responseModelAdapter); - ArgumentGuard.NotNull(exceptionHandler); - ArgumentGuard.NotNull(eTagGenerator); - ArgumentGuard.NotNull(options); - ArgumentGuard.NotNull(loggerFactory); + ArgumentNullException.ThrowIfNull(request); + ArgumentNullException.ThrowIfNull(responseModelAdapter); + ArgumentNullException.ThrowIfNull(exceptionHandler); + ArgumentNullException.ThrowIfNull(eTagGenerator); + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(logger); _request = request; _options = options; _responseModelAdapter = responseModelAdapter; _exceptionHandler = exceptionHandler; _eTagGenerator = eTagGenerator; - _traceWriter = new TraceLogWriter(loggerFactory); + _logger = logger; } /// public async Task WriteAsync(object? model, HttpContext httpContext) { - ArgumentGuard.NotNull(httpContext); + ArgumentNullException.ThrowIfNull(httpContext); if (model == null && !CanWriteBody((HttpStatusCode)httpContext.Response.StatusCode)) { @@ -71,16 +63,15 @@ public async Task WriteAsync(object? model, HttpContext httpContext) return; } - _traceWriter.LogMessage(() => + if (_logger.IsEnabled(LogLevel.Trace)) { - string method = httpContext.Request.Method.Replace(Environment.NewLine, ""); - string url = httpContext.Request.GetEncodedUrl(); - - return $"Sending {httpContext.Response.StatusCode} response for {method} request at '{url}' with body: <<{responseBody}>>"; - }); + string requestMethod = httpContext.Request.Method.Replace(Environment.NewLine, ""); + string requestUrl = httpContext.Request.GetEncodedUrl(); + LogResponse(requestMethod, requestUrl, responseBody, httpContext.Response.StatusCode); + } - string responseContentType = GetResponseContentType(httpContext.Request); - await SendResponseBodyAsync(httpContext.Response, responseBody, responseContentType); + var responseMediaType = new JsonApiMediaType(_request.Extensions); + await SendResponseBodyAsync(httpContext.Response, responseBody, responseMediaType.ToString()); } private static bool CanWriteBody(HttpStatusCode statusCode) @@ -162,8 +153,8 @@ private bool SetETagResponseHeader(HttpRequest request, HttpResponse response, s private static bool RequestContainsMatchingETag(IHeaderDictionary requestHeaders, EntityTagHeaderValue responseETag) { - if (requestHeaders.Keys.Contains(HeaderNames.IfNoneMatch) && - EntityTagHeaderValue.TryParseList(requestHeaders[HeaderNames.IfNoneMatch], out IList? requestETags)) + if (requestHeaders.TryGetValue(HeaderNames.IfNoneMatch, out StringValues headerValues) && + EntityTagHeaderValue.TryParseList(headerValues, out IList? requestETags)) { foreach (EntityTagHeaderValue requestETag in requestETags) { @@ -177,39 +168,6 @@ private static bool RequestContainsMatchingETag(IHeaderDictionary requestHeaders return false; } - private string GetResponseContentType(HttpRequest httpRequest) - { - if (_request.Kind != EndpointKind.AtomicOperations) - { - return HeaderConstants.MediaType; - } - - MediaTypeHeaderValue? bestMatch = null; - - foreach (MediaTypeHeaderValue headerValue in httpRequest.GetTypedHeaders().Accept) - { - double quality = headerValue.Quality ?? 1.0; - headerValue.Quality = null; - - if (AllowedOperationsMediaTypes.Contains(headerValue)) - { - if (bestMatch == null || bestMatch.Quality < quality) - { - headerValue.Quality = quality; - bestMatch = headerValue; - } - } - } - - if (bestMatch == null) - { - return httpRequest.ContentType ?? HeaderConstants.AtomicOperationsMediaType; - } - - bestMatch.Quality = null; - return RelaxedOperationsMediaType.Equals(bestMatch) ? HeaderConstants.RelaxedAtomicOperationsMediaType : HeaderConstants.AtomicOperationsMediaType; - } - private async Task SendResponseBodyAsync(HttpResponse httpResponse, string? responseBody, string contentType) { if (!string.IsNullOrEmpty(responseBody)) @@ -223,4 +181,8 @@ private async Task SendResponseBodyAsync(HttpResponse httpResponse, string? resp await writer.FlushAsync(); } } + + [LoggerMessage(Level = LogLevel.Trace, SkipEnabledCheck = true, + Message = "Sending {ResponseStatusCode} response for {RequestMethod} request at '{RequestUrl}' with body: <<{ResponseBody}>>")] + private partial void LogResponse(string requestMethod, string requestUrl, string? responseBody, int responseStatusCode); } diff --git a/src/JsonApiDotNetCore/Serialization/Response/LinkBuilder.cs b/src/JsonApiDotNetCore/Serialization/Response/LinkBuilder.cs index 27cf775d70..b7f200dd48 100644 --- a/src/JsonApiDotNetCore/Serialization/Response/LinkBuilder.cs +++ b/src/JsonApiDotNetCore/Serialization/Response/LinkBuilder.cs @@ -56,13 +56,13 @@ public LinkBuilder(IJsonApiOptions options, IJsonApiRequest request, IPagination LinkGenerator linkGenerator, IControllerResourceMapping controllerResourceMapping, IPaginationParser paginationParser, IDocumentDescriptionLinkProvider documentDescriptionLinkProvider) { - ArgumentGuard.NotNull(options); - ArgumentGuard.NotNull(request); - ArgumentGuard.NotNull(paginationContext); - ArgumentGuard.NotNull(linkGenerator); - ArgumentGuard.NotNull(controllerResourceMapping); - ArgumentGuard.NotNull(paginationParser); - ArgumentGuard.NotNull(documentDescriptionLinkProvider); + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(request); + ArgumentNullException.ThrowIfNull(paginationContext); + ArgumentNullException.ThrowIfNull(linkGenerator); + ArgumentNullException.ThrowIfNull(controllerResourceMapping); + ArgumentNullException.ThrowIfNull(paginationParser); + ArgumentNullException.ThrowIfNull(documentDescriptionLinkProvider); _options = options; _request = request; @@ -189,7 +189,7 @@ private void SetPaginationInTopLevelLinks(ResourceType resourceType, TopLevelLin string parameterValue = string.Join(',', elements.Select(expression => expression.Scope == null ? expression.Value.ToString() : $"{expression.Scope}:{expression.Value}")); - return parameterValue == string.Empty ? null : parameterValue; + return parameterValue.Length == 0 ? null : parameterValue; } private IImmutableList ParsePageSizeExpression(string? pageSizeParameterValue, ResourceType resourceType) @@ -219,7 +219,7 @@ private string GetLinkForPagination(int pageOffset, string? pageSizeValue) private string GetQueryStringInPaginationLink(int pageOffset, string? pageSizeValue) { - IDictionary parameters = HttpContext.Request.Query.ToDictionary(pair => pair.Key, pair => (string?)pair.Value.ToString()); + Dictionary parameters = HttpContext.Request.Query.ToDictionary(pair => pair.Key, pair => (string?)pair.Value.ToString()); if (pageSizeValue == null) { @@ -245,8 +245,8 @@ private string GetQueryStringInPaginationLink(int pageOffset, string? pageSizeVa /// public ResourceLinks? GetResourceLinks(ResourceType resourceType, IIdentifiable resource) { - ArgumentGuard.NotNull(resourceType); - ArgumentGuard.NotNull(resource); + ArgumentNullException.ThrowIfNull(resourceType); + ArgumentNullException.ThrowIfNull(resource); var links = new ResourceLinks(); @@ -275,7 +275,7 @@ private bool ShouldIncludeResourceLink(LinkTypes linkType, ResourceType resource private string? GetLinkForResourceSelf(ResourceType resourceType, IIdentifiable resource) { string? controllerName = _controllerResourceMapping.GetControllerNameForResourceType(resourceType); - IDictionary routeValues = GetRouteValues(resource.StringId!, null); + RouteValueDictionary routeValues = GetRouteValues(resource.StringId!, null); return RenderLinkForAction(controllerName, GetPrimaryControllerActionName, routeValues); } @@ -283,8 +283,8 @@ private bool ShouldIncludeResourceLink(LinkTypes linkType, ResourceType resource /// public RelationshipLinks? GetRelationshipLinks(RelationshipAttribute relationship, IIdentifiable leftResource) { - ArgumentGuard.NotNull(relationship); - ArgumentGuard.NotNull(leftResource); + ArgumentNullException.ThrowIfNull(relationship); + ArgumentNullException.ThrowIfNull(leftResource); var links = new RelationshipLinks(); @@ -304,7 +304,7 @@ private bool ShouldIncludeResourceLink(LinkTypes linkType, ResourceType resource private string? GetLinkForRelationshipSelf(string leftId, RelationshipAttribute relationship) { string? controllerName = _controllerResourceMapping.GetControllerNameForResourceType(relationship.LeftType); - IDictionary routeValues = GetRouteValues(leftId, relationship.PublicName); + RouteValueDictionary routeValues = GetRouteValues(leftId, relationship.PublicName); return RenderLinkForAction(controllerName, GetRelationshipControllerActionName, routeValues); } @@ -312,12 +312,12 @@ private bool ShouldIncludeResourceLink(LinkTypes linkType, ResourceType resource private string? GetLinkForRelationshipRelated(string leftId, RelationshipAttribute relationship) { string? controllerName = _controllerResourceMapping.GetControllerNameForResourceType(relationship.LeftType); - IDictionary routeValues = GetRouteValues(leftId, relationship.PublicName); + RouteValueDictionary routeValues = GetRouteValues(leftId, relationship.PublicName); return RenderLinkForAction(controllerName, GetSecondaryControllerActionName, routeValues); } - private IDictionary GetRouteValues(string primaryId, string? relationshipName) + private RouteValueDictionary GetRouteValues(string primaryId, string? relationshipName) { // By default, we copy all route parameters from the *current* endpoint, which helps in case all endpoints have the same // set of non-standard parameters. There is no way we can know which non-standard parameters a *different* endpoint needs, @@ -332,6 +332,9 @@ private bool ShouldIncludeResourceLink(LinkTypes linkType, ResourceType resource protected virtual string? RenderLinkForAction(string? controllerName, string actionName, IDictionary routeValues) { + ArgumentNullException.ThrowIfNull(actionName); + ArgumentNullException.ThrowIfNull(routeValues); + if (controllerName == null) { // When passing null to LinkGenerator, it uses the controller for the current endpoint. This is incorrect for diff --git a/src/JsonApiDotNetCore/Serialization/Response/MetaBuilder.cs b/src/JsonApiDotNetCore/Serialization/Response/MetaBuilder.cs index a5e647c853..1c3cc604e3 100644 --- a/src/JsonApiDotNetCore/Serialization/Response/MetaBuilder.cs +++ b/src/JsonApiDotNetCore/Serialization/Response/MetaBuilder.cs @@ -16,9 +16,9 @@ public sealed class MetaBuilder : IMetaBuilder public MetaBuilder(IPaginationContext paginationContext, IJsonApiOptions options, IResponseMeta responseMeta) { - ArgumentGuard.NotNull(paginationContext); - ArgumentGuard.NotNull(options); - ArgumentGuard.NotNull(responseMeta); + ArgumentNullException.ThrowIfNull(paginationContext); + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(responseMeta); _paginationContext = paginationContext; _options = options; @@ -28,7 +28,7 @@ public MetaBuilder(IPaginationContext paginationContext, IJsonApiOptions options /// public void Add(IDictionary values) { - ArgumentGuard.NotNull(values); + ArgumentNullException.ThrowIfNull(values); _meta = values.Keys.Union(_meta.Keys).ToDictionary(key => key, key => values.TryGetValue(key, out object? value) ? value : _meta[key]); } @@ -50,6 +50,6 @@ public void Add(IDictionary values) Add(extraMeta); } - return _meta.Any() ? _meta : null; + return _meta.Count > 0 ? _meta : null; } } diff --git a/src/JsonApiDotNetCore/Serialization/Response/ResourceObjectTreeNode.cs b/src/JsonApiDotNetCore/Serialization/Response/ResourceObjectTreeNode.cs index ab50d6f674..2ded4ae896 100644 --- a/src/JsonApiDotNetCore/Serialization/Response/ResourceObjectTreeNode.cs +++ b/src/JsonApiDotNetCore/Serialization/Response/ResourceObjectTreeNode.cs @@ -37,9 +37,9 @@ internal sealed class ResourceObjectTreeNode : IEquatable GetUniqueNodes() { AssertIsTreeRoot(); - var visited = new HashSet(); + HashSet visited = []; VisitSubtree(this, visited); - return visited; + return visited.AsReadOnly(); } private static void VisitSubtree(ResourceObjectTreeNode treeNode, ISet visited) @@ -151,7 +151,7 @@ private static void VisitRelationshipChildInSubtree(HashSet? GetRightNodesInRelationship(RelationshipAttribute relationship) { return _childrenByRelationship != null && _childrenByRelationship.TryGetValue(relationship, out HashSet? rightNodes) - ? rightNodes + ? rightNodes.AsReadOnly() : null; } @@ -162,7 +162,7 @@ public IReadOnlyList GetResponseData() { AssertIsTreeRoot(); - return GetDirectChildren().Select(child => child.ResourceObject).ToArray(); + return GetDirectChildren().Select(child => child.ResourceObject).ToArray().AsReadOnly(); } /// @@ -174,14 +174,14 @@ public IList GetResponseIncluded() { AssertIsTreeRoot(); - var visited = new HashSet(); + HashSet visited = []; foreach (ResourceObjectTreeNode child in GetDirectChildren()) { VisitRelationshipChildrenInSubtree(child, visited); } - ISet primaryResourceObjectSet = GetDirectChildren().Select(node => node.ResourceObject).ToHashSet(ResourceObjectComparer.Instance); + HashSet primaryResourceObjectSet = GetDirectChildren().Select(node => node.ResourceObject).ToHashSet(ResourceObjectComparer.Instance); List includes = []; foreach (ResourceObject include in visited.Select(node => node.ResourceObject)) @@ -210,7 +210,7 @@ private void AssertIsTreeRoot() public bool Equals(ResourceObjectTreeNode? other) { - if (ReferenceEquals(null, other)) + if (other is null) { return false; } diff --git a/src/JsonApiDotNetCore/Serialization/Response/ResponseModelAdapter.cs b/src/JsonApiDotNetCore/Serialization/Response/ResponseModelAdapter.cs index 9457b05502..80f7809255 100644 --- a/src/JsonApiDotNetCore/Serialization/Response/ResponseModelAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Response/ResponseModelAdapter.cs @@ -18,8 +18,6 @@ namespace JsonApiDotNetCore.Serialization.Response; [PublicAPI] public class ResponseModelAdapter : IResponseModelAdapter { - private static readonly CollectionConverter CollectionConverter = new(); - private readonly IJsonApiRequest _request; private readonly IJsonApiOptions _options; private readonly ILinkBuilder _linkBuilder; @@ -36,14 +34,14 @@ public ResponseModelAdapter(IJsonApiRequest request, IJsonApiOptions options, IL IResourceDefinitionAccessor resourceDefinitionAccessor, IEvaluatedIncludeCache evaluatedIncludeCache, ISparseFieldSetCache sparseFieldSetCache, IRequestQueryStringAccessor requestQueryStringAccessor) { - ArgumentGuard.NotNull(request); - ArgumentGuard.NotNull(options); - ArgumentGuard.NotNull(linkBuilder); - ArgumentGuard.NotNull(metaBuilder); - ArgumentGuard.NotNull(resourceDefinitionAccessor); - ArgumentGuard.NotNull(evaluatedIncludeCache); - ArgumentGuard.NotNull(sparseFieldSetCache); - ArgumentGuard.NotNull(requestQueryStringAccessor); + ArgumentNullException.ThrowIfNull(request); + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(linkBuilder); + ArgumentNullException.ThrowIfNull(metaBuilder); + ArgumentNullException.ThrowIfNull(resourceDefinitionAccessor); + ArgumentNullException.ThrowIfNull(evaluatedIncludeCache); + ArgumentNullException.ThrowIfNull(sparseFieldSetCache); + ArgumentNullException.ThrowIfNull(requestQueryStringAccessor); _request = request; _options = options; @@ -103,11 +101,12 @@ public Document Convert(object? model) } else if (model is IEnumerable errorObjects) { - document.Errors = errorObjects.ToArray(); + document.Errors = errorObjects.ToList(); } else if (model is ErrorObject errorObject) { - document.Errors = [errorObject]; + List errors = [errorObject]; + document.Errors = errors; } else { @@ -124,6 +123,8 @@ public Document Convert(object? model) protected virtual AtomicResultObject ConvertOperation(OperationContainer? operation, IImmutableSet includeElements) { + ArgumentNullException.ThrowIfNull(includeElements); + ResourceObject? resourceObject = null; if (operation != null) @@ -205,6 +206,9 @@ private static ResourceType GetEffectiveResourceType(IIdentifiable resource, Res protected virtual ResourceObject ConvertResource(IIdentifiable resource, ResourceType resourceType, EndpointKind kind) { + ArgumentNullException.ThrowIfNull(resource); + ArgumentNullException.ThrowIfNull(resourceType); + bool isRelationship = kind == EndpointKind.Relationship; if (!isRelationship) @@ -235,6 +239,10 @@ protected virtual ResourceObject ConvertResource(IIdentifiable resource, Resourc #pragma warning restore AV1130 // Return type in method signature should be an interface to an unchangeable collection IImmutableSet fieldSet) { + ArgumentNullException.ThrowIfNull(resource); + ArgumentNullException.ThrowIfNull(resourceType); + ArgumentNullException.ThrowIfNull(fieldSet); + var attrMap = new Dictionary(resourceType.Attributes.Count); foreach (AttrAttribute attr in resourceType.Attributes) @@ -260,7 +268,7 @@ protected virtual ResourceObject ConvertResource(IIdentifiable resource, Resourc attrMap.Add(attr.PublicName, value); } - return attrMap.Any() ? attrMap : null; + return attrMap.Count > 0 ? attrMap : null; } private void TraverseRelationships(IIdentifiable leftResource, ResourceObjectTreeNode leftTreeNode, IImmutableSet includeElements, @@ -294,7 +302,7 @@ private void TraverseRelationship(RelationshipAttribute relationship, IIdentifia } object? rightValue = effectiveRelationship.GetValue(leftResource); - IReadOnlyCollection rightResources = CollectionConverter.ExtractResources(rightValue); + IReadOnlyCollection rightResources = CollectionConverter.Instance.ExtractResources(rightValue); leftTreeNode.EnsureHasRelationship(effectiveRelationship); @@ -393,7 +401,7 @@ private static SingleOrManyData GetRelationshipData(Re { IList resourceObjects = rootNode.GetResponseIncluded(); - if (resourceObjects.Any()) + if (resourceObjects.Count > 0) { return resourceObjects; } diff --git a/src/JsonApiDotNetCore/Serialization/Response/UriNormalizer.cs b/src/JsonApiDotNetCore/Serialization/Response/UriNormalizer.cs index 5b2517f4b0..f0d9a7400d 100644 --- a/src/JsonApiDotNetCore/Serialization/Response/UriNormalizer.cs +++ b/src/JsonApiDotNetCore/Serialization/Response/UriNormalizer.cs @@ -70,11 +70,6 @@ private static bool AreSameServer(Uri left, Uri right) string leftUserInfo = left.GetComponents(UriComponents.UserInfo, UriFormat.UriEscaped); string rightUserInfo = right.GetComponents(UriComponents.UserInfo, UriFormat.UriEscaped); - if (!string.Equals(leftUserInfo, rightUserInfo)) - { - return false; - } - - return true; + return leftUserInfo == rightUserInfo; } } diff --git a/src/JsonApiDotNetCore/Services/AsyncCollectionExtensions.cs b/src/JsonApiDotNetCore/Services/AsyncCollectionExtensions.cs index 11e483b419..83ba8902a2 100644 --- a/src/JsonApiDotNetCore/Services/AsyncCollectionExtensions.cs +++ b/src/JsonApiDotNetCore/Services/AsyncCollectionExtensions.cs @@ -7,8 +7,8 @@ public static class AsyncCollectionExtensions { public static async Task AddRangeAsync(this ICollection source, IAsyncEnumerable elementsToAdd, CancellationToken cancellationToken = default) { - ArgumentGuard.NotNull(source); - ArgumentGuard.NotNull(elementsToAdd); + ArgumentNullException.ThrowIfNull(source); + ArgumentNullException.ThrowIfNull(elementsToAdd); await foreach (T missingResource in elementsToAdd.WithCancellation(cancellationToken)) { @@ -18,9 +18,9 @@ public static async Task AddRangeAsync(this ICollection source, IAsyncEnum public static async Task> ToListAsync(this IAsyncEnumerable source, CancellationToken cancellationToken = default) { - ArgumentGuard.NotNull(source); + ArgumentNullException.ThrowIfNull(source); - var list = new List(); + List list = []; await foreach (T element in source.WithCancellation(cancellationToken)) { diff --git a/src/JsonApiDotNetCore/Services/JsonApiResourceService.cs b/src/JsonApiDotNetCore/Services/JsonApiResourceService.cs index 478d38ab72..de5d3b7b1f 100644 --- a/src/JsonApiDotNetCore/Services/JsonApiResourceService.cs +++ b/src/JsonApiDotNetCore/Services/JsonApiResourceService.cs @@ -21,7 +21,6 @@ namespace JsonApiDotNetCore.Services; public class JsonApiResourceService : IResourceService where TResource : class, IIdentifiable { - private readonly CollectionConverter _collectionConverter = new(); private readonly IResourceRepositoryAccessor _repositoryAccessor; private readonly IQueryLayerComposer _queryLayerComposer; private readonly IPaginationContext _paginationContext; @@ -35,14 +34,14 @@ public JsonApiResourceService(IResourceRepositoryAccessor repositoryAccessor, IQ IJsonApiOptions options, ILoggerFactory loggerFactory, IJsonApiRequest request, IResourceChangeTracker resourceChangeTracker, IResourceDefinitionAccessor resourceDefinitionAccessor) { - ArgumentGuard.NotNull(repositoryAccessor); - ArgumentGuard.NotNull(queryLayerComposer); - ArgumentGuard.NotNull(paginationContext); - ArgumentGuard.NotNull(options); - ArgumentGuard.NotNull(loggerFactory); - ArgumentGuard.NotNull(request); - ArgumentGuard.NotNull(resourceChangeTracker); - ArgumentGuard.NotNull(resourceDefinitionAccessor); + ArgumentNullException.ThrowIfNull(repositoryAccessor); + ArgumentNullException.ThrowIfNull(queryLayerComposer); + ArgumentNullException.ThrowIfNull(paginationContext); + ArgumentNullException.ThrowIfNull(options); + ArgumentNullException.ThrowIfNull(loggerFactory); + ArgumentNullException.ThrowIfNull(request); + ArgumentNullException.ThrowIfNull(resourceChangeTracker); + ArgumentNullException.ThrowIfNull(resourceDefinitionAccessor); _repositoryAccessor = repositoryAccessor; _queryLayerComposer = queryLayerComposer; @@ -59,10 +58,10 @@ public virtual async Task> GetAsync(CancellationT { _traceWriter.LogMethodStart(); - using IDisposable _ = CodeTimingSessionManager.Current.Measure("Service - Get resources"); - AssertPrimaryResourceTypeInJsonApiRequestIsNotNull(_request.PrimaryResourceType); + using IDisposable _ = CodeTimingSessionManager.Current.Measure("Service - Get resources"); + if (_options.IncludeTotalResourceCount) { FilterExpression? topFilter = _queryLayerComposer.GetPrimaryFilterFromConstraints(_request.PrimaryResourceType); @@ -107,11 +106,12 @@ public virtual async Task GetAsync([DisallowNull] TId id, Cancellatio relationshipName }); - using IDisposable _ = CodeTimingSessionManager.Current.Measure("Service - Get secondary resource(s)"); - + ArgumentNullException.ThrowIfNull(relationshipName); AssertPrimaryResourceTypeInJsonApiRequestIsNotNull(_request.PrimaryResourceType); AssertHasRelationship(_request.Relationship, relationshipName); + using IDisposable _ = CodeTimingSessionManager.Current.Measure("Service - Get secondary resource(s)"); + if (_options.IncludeTotalResourceCount && _request.IsCollection) { await RetrieveResourceCountForNonPrimaryEndpointAsync(id, (HasManyAttribute)_request.Relationship, cancellationToken); @@ -146,13 +146,12 @@ public virtual async Task GetAsync([DisallowNull] TId id, Cancellatio relationshipName }); - ArgumentGuard.NotNullNorEmpty(relationshipName); - - using IDisposable _ = CodeTimingSessionManager.Current.Measure("Service - Get relationship"); - + ArgumentNullException.ThrowIfNull(relationshipName); AssertPrimaryResourceTypeInJsonApiRequestIsNotNull(_request.PrimaryResourceType); AssertHasRelationship(_request.Relationship, relationshipName); + using IDisposable _ = CodeTimingSessionManager.Current.Measure("Service - Get relationship"); + if (_options.IncludeTotalResourceCount && _request.IsCollection) { await RetrieveResourceCountForNonPrimaryEndpointAsync(id, (HasManyAttribute)_request.Relationship, cancellationToken); @@ -197,7 +196,7 @@ private async Task RetrieveResourceCountForNonPrimaryEndpointAsync([DisallowNull resource }); - ArgumentGuard.NotNull(resource); + ArgumentNullException.ThrowIfNull(resource); using IDisposable _ = CodeTimingSessionManager.Current.Measure("Service - Create resource"); @@ -238,6 +237,8 @@ private async Task RetrieveResourceCountForNonPrimaryEndpointAsync([DisallowNull protected async Task AssertPrimaryResourceDoesNotExistAsync(TResource resource, CancellationToken cancellationToken) { + ArgumentNullException.ThrowIfNull(resource); + if (!Equals(resource.Id, default(TId))) { TResource? existingResource = await GetPrimaryResourceByIdOrDefaultAsync(resource.Id!, TopFieldSelection.OnlyIdAttribute, cancellationToken); @@ -251,6 +252,8 @@ protected async Task AssertPrimaryResourceDoesNotExistAsync(TResource resource, protected virtual async Task InitializeResourceAsync(TResource resourceForDatabase, CancellationToken cancellationToken) { + ArgumentNullException.ThrowIfNull(resourceForDatabase); + await _resourceDefinitionAccessor.OnPrepareWriteAsync(resourceForDatabase, WriteOperationKind.CreateResource, cancellationToken); } @@ -261,22 +264,24 @@ private async Task AccurizeResourceTypesInHierarchyToAssignInRelationshipsAsync( protected async Task AssertResourcesToAssignInRelationshipsExistAsync(TResource primaryResource, CancellationToken cancellationToken) { + ArgumentNullException.ThrowIfNull(primaryResource); + await ValidateResourcesToAssignInRelationshipsExistWithRefreshAsync(primaryResource, false, cancellationToken); } private async Task ValidateResourcesToAssignInRelationshipsExistWithRefreshAsync(TResource primaryResource, bool onlyIfTypeHierarchy, CancellationToken cancellationToken) { - var missingResources = new List(); + List missingResources = []; foreach ((QueryLayer queryLayer, RelationshipAttribute relationship) in _queryLayerComposer.ComposeForGetTargetedSecondaryResourceIds(primaryResource)) { if (!onlyIfTypeHierarchy || relationship.RightType.IsPartOfTypeHierarchy()) { object? rightValue = relationship.GetValue(primaryResource); - HashSet rightResourceIds = _collectionConverter.ExtractResources(rightValue).ToHashSet(IdentifiableComparer.Instance); + HashSet rightResourceIds = CollectionConverter.Instance.ExtractResources(rightValue).ToHashSet(IdentifiableComparer.Instance); - if (rightResourceIds.Any()) + if (rightResourceIds.Count > 0) { IAsyncEnumerable missingResourcesInRelationship = GetMissingRightResourcesAsync(queryLayer, relationship, rightResourceIds, cancellationToken); @@ -287,21 +292,21 @@ private async Task ValidateResourcesToAssignInRelationshipsExistWithRefreshAsync // Now that we've fetched them, update the request types so that resource definitions observe the actually stored types. object? newRightValue = relationship is HasOneAttribute ? rightResourceIds.FirstOrDefault() - : _collectionConverter.CopyToTypedCollection(rightResourceIds, relationship.Property.PropertyType); + : CollectionConverter.Instance.CopyToTypedCollection(rightResourceIds, relationship.Property.PropertyType); relationship.SetValue(primaryResource, newRightValue); } } } - if (missingResources.Any()) + if (missingResources.Count > 0) { throw new ResourcesInRelationshipsNotFoundException(missingResources); } } private async IAsyncEnumerable GetMissingRightResourcesAsync(QueryLayer existingRightResourceIdsQueryLayer, - RelationshipAttribute relationship, ISet rightResourceIds, [EnumeratorCancellation] CancellationToken cancellationToken) + RelationshipAttribute relationship, HashSet rightResourceIds, [EnumeratorCancellation] CancellationToken cancellationToken) { IReadOnlyCollection existingResources = await _repositoryAccessor.GetAsync(existingRightResourceIdsQueryLayer.ResourceType, existingRightResourceIdsQueryLayer, cancellationToken); @@ -344,16 +349,15 @@ public virtual async Task AddToToManyRelationshipAsync([DisallowNull] TId leftId rightResourceIds }); - ArgumentGuard.NotNullNorEmpty(relationshipName); - ArgumentGuard.NotNull(rightResourceIds); + ArgumentNullException.ThrowIfNull(relationshipName); + ArgumentNullException.ThrowIfNull(rightResourceIds); + AssertHasRelationship(_request.Relationship, relationshipName); using IDisposable _ = CodeTimingSessionManager.Current.Measure("Service - Add to to-many relationship"); - AssertHasRelationship(_request.Relationship, relationshipName); - TResource? resourceFromDatabase = null; - if (rightResourceIds.Any() && _request.Relationship is HasManyAttribute { IsManyToMany: true } manyToManyRelationship) + if (rightResourceIds.Count > 0 && _request.Relationship is HasManyAttribute { IsManyToMany: true } manyToManyRelationship) { // In the case of a many-to-many relationship, creating a duplicate entry in the join table results in a // unique constraint violation. We avoid that by excluding already-existing entries from the set in advance. @@ -396,7 +400,7 @@ private async Task RemoveExistingIdsFromRelationshipRightSideAsync(Ha TResource leftResource = await GetForHasManyUpdateAsync(hasManyRelationship, leftId, rightResourceIds, cancellationToken); object? rightValue = hasManyRelationship.GetValue(leftResource); - IReadOnlyCollection existingRightResourceIds = _collectionConverter.ExtractResources(rightValue); + IReadOnlyCollection existingRightResourceIds = CollectionConverter.Instance.ExtractResources(rightValue); rightResourceIds.ExceptWith(existingRightResourceIds); @@ -417,10 +421,10 @@ private async Task GetForHasManyUpdateAsync(HasManyAttribute hasManyR { AssertRelationshipInJsonApiRequestIsNotNull(_request.Relationship); - HashSet rightResourceIds = _collectionConverter.ExtractResources(rightValue).ToHashSet(IdentifiableComparer.Instance); + HashSet rightResourceIds = CollectionConverter.Instance.ExtractResources(rightValue).ToHashSet(IdentifiableComparer.Instance); object? newRightValue = rightValue; - if (rightResourceIds.Any()) + if (rightResourceIds.Count > 0) { QueryLayer queryLayer = _queryLayerComposer.ComposeForGetRelationshipRightIds(_request.Relationship, rightResourceIds); @@ -431,9 +435,9 @@ private async Task GetForHasManyUpdateAsync(HasManyAttribute hasManyR // Now that we've fetched them, update the request types so that resource definitions observe the actually stored types. newRightValue = _request.Relationship is HasOneAttribute ? rightResourceIds.FirstOrDefault() - : _collectionConverter.CopyToTypedCollection(rightResourceIds, _request.Relationship.Property.PropertyType); + : CollectionConverter.Instance.CopyToTypedCollection(rightResourceIds, _request.Relationship.Property.PropertyType); - if (missingResources.Any()) + if (missingResources.Count > 0) { throw new ResourcesInRelationshipsNotFoundException(missingResources); } @@ -451,7 +455,7 @@ private async Task GetForHasManyUpdateAsync(HasManyAttribute hasManyR resource }); - ArgumentGuard.NotNull(resource); + ArgumentNullException.ThrowIfNull(resource); using IDisposable _ = CodeTimingSessionManager.Current.Measure("Service - Update resource"); @@ -495,12 +499,11 @@ public virtual async Task SetRelationshipAsync([DisallowNull] TId leftId, string rightValue }); - ArgumentGuard.NotNullNorEmpty(relationshipName); + ArgumentNullException.ThrowIfNull(relationshipName); + AssertHasRelationship(_request.Relationship, relationshipName); using IDisposable _ = CodeTimingSessionManager.Current.Measure("Service - Set relationship"); - AssertHasRelationship(_request.Relationship, relationshipName); - object? effectiveRightValue = _request.Relationship.RightType.IsPartOfTypeHierarchy() // Some of the incoming right-side resources may be stored as a derived type. We fetch them, so we'll know // the stored types, which enables to invoke resource definitions with the stored right-side resources types. @@ -531,10 +534,10 @@ public virtual async Task DeleteAsync([DisallowNull] TId id, CancellationToken c id }); - using IDisposable _ = CodeTimingSessionManager.Current.Measure("Repository - Delete resource"); - AssertPrimaryResourceTypeInJsonApiRequestIsNotNull(_request.PrimaryResourceType); + using IDisposable _ = CodeTimingSessionManager.Current.Measure("Repository - Delete resource"); + TResource? resourceFromDatabase = null; if (_request.PrimaryResourceType.IsPartOfTypeHierarchy()) @@ -567,12 +570,12 @@ public virtual async Task RemoveFromToManyRelationshipAsync([DisallowNull] TId l rightResourceIds }); - ArgumentGuard.NotNullNorEmpty(relationshipName); - ArgumentGuard.NotNull(rightResourceIds); + ArgumentNullException.ThrowIfNull(relationshipName); + ArgumentNullException.ThrowIfNull(rightResourceIds); + AssertHasRelationship(_request.Relationship, relationshipName); using IDisposable _ = CodeTimingSessionManager.Current.Measure("Repository - Remove from to-many relationship"); - AssertHasRelationship(_request.Relationship, relationshipName); var hasManyRelationship = (HasManyAttribute)_request.Relationship; TResource resourceFromDatabase = await GetForHasManyUpdateAsync(hasManyRelationship, leftId, rightResourceIds, cancellationToken); @@ -597,9 +600,10 @@ protected async Task GetPrimaryResourceByIdAsync([DisallowNull] TId i private async Task GetPrimaryResourceByIdOrDefaultAsync([DisallowNull] TId id, TopFieldSelection fieldSelection, CancellationToken cancellationToken) { - AssertPrimaryResourceTypeInJsonApiRequestIsNotNull(_request.PrimaryResourceType); + // Using the non-accurized resource type, so that includes on sibling derived types can be used at abstract endpoint. + ResourceType resourceType = _repositoryAccessor.LookupResourceType(typeof(TResource)); - QueryLayer primaryLayer = _queryLayerComposer.ComposeForGetById(id, _request.PrimaryResourceType, fieldSelection); + QueryLayer primaryLayer = _queryLayerComposer.ComposeForGetById(id, resourceType, fieldSelection); IReadOnlyCollection primaryResources = await _repositoryAccessor.GetAsync(primaryLayer, cancellationToken); return primaryResources.SingleOrDefault(); diff --git a/test/AnnotationTests/AnnotationTests.csproj b/test/AnnotationTests/AnnotationTests.csproj index 081046adb0..885e9f769c 100644 --- a/test/AnnotationTests/AnnotationTests.csproj +++ b/test/AnnotationTests/AnnotationTests.csproj @@ -1,6 +1,6 @@ - net8.0;net6.0;netstandard2.0 + net9.0;net8.0;netstandard2.0 diff --git a/test/DapperTests/DapperTests.csproj b/test/DapperTests/DapperTests.csproj index 45d9c6a88d..7d41d78911 100644 --- a/test/DapperTests/DapperTests.csproj +++ b/test/DapperTests/DapperTests.csproj @@ -1,6 +1,6 @@ - net8.0;net6.0 + net9.0;net8.0 diff --git a/test/DapperTests/IntegrationTests/AtomicOperations/AtomicOperationsTests.cs b/test/DapperTests/IntegrationTests/AtomicOperations/AtomicOperationsTests.cs index a3d665cc61..64acaaa57f 100644 --- a/test/DapperTests/IntegrationTests/AtomicOperations/AtomicOperationsTests.cs +++ b/test/DapperTests/IntegrationTests/AtomicOperations/AtomicOperationsTests.cs @@ -29,10 +29,10 @@ public async Task Can_use_multiple_operations() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person newOwner = _fakers.Person.Generate(); - Person newAssignee = _fakers.Person.Generate(); - Tag newTag = _fakers.Tag.Generate(); - TodoItem newTodoItem = _fakers.TodoItem.Generate(); + Person newOwner = _fakers.Person.GenerateOne(); + Person newAssignee = _fakers.Person.GenerateOne(); + Tag newTag = _fakers.Tag.GenerateOne(); + TodoItem newTodoItem = _fakers.TodoItem.GenerateOne(); const string ownerLocalId = "new-owner"; const string assigneeLocalId = "new-assignee"; @@ -168,20 +168,20 @@ public async Task Can_use_multiple_operations() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(7); + responseDocument.Results.Should().HaveCount(7); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => resource.Type.Should().Be("people")); - responseDocument.Results[1].Data.SingleValue.ShouldNotBeNull().With(resource => resource.Type.Should().Be("people")); - responseDocument.Results[2].Data.SingleValue.ShouldNotBeNull().With(resource => resource.Type.Should().Be("tags")); - responseDocument.Results[3].Data.SingleValue.ShouldNotBeNull().With(resource => resource.Type.Should().Be("todoItems")); + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.Type.Should().Be("people"); + responseDocument.Results[1].Data.SingleValue.RefShould().NotBeNull().And.Subject.Type.Should().Be("people"); + responseDocument.Results[2].Data.SingleValue.RefShould().NotBeNull().And.Subject.Type.Should().Be("tags"); + responseDocument.Results[3].Data.SingleValue.RefShould().NotBeNull().And.Subject.Type.Should().Be("todoItems"); responseDocument.Results[4].Data.Value.Should().BeNull(); - responseDocument.Results[5].Data.SingleValue.ShouldNotBeNull().With(resource => resource.Type.Should().Be("todoItems")); + responseDocument.Results[5].Data.SingleValue.RefShould().NotBeNull().And.Subject.Type.Should().Be("todoItems"); responseDocument.Results[6].Data.Value.Should().BeNull(); - long newOwnerId = long.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); - long newAssigneeId = long.Parse(responseDocument.Results[1].Data.SingleValue!.Id.ShouldNotBeNull()); - long newTagId = long.Parse(responseDocument.Results[2].Data.SingleValue!.Id.ShouldNotBeNull()); - long newTodoItemId = long.Parse(responseDocument.Results[3].Data.SingleValue!.Id.ShouldNotBeNull()); + long newOwnerId = long.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); + long newAssigneeId = long.Parse(responseDocument.Results[1].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); + long newTagId = long.Parse(responseDocument.Results[2].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); + long newTodoItemId = long.Parse(responseDocument.Results[3].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -203,14 +203,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => todoItemInDatabase.CreatedAt.Should().Be(DapperTestContext.FrozenTime); todoItemInDatabase.LastModifiedAt.Should().Be(DapperTestContext.FrozenTime); - todoItemInDatabase.Owner.ShouldNotBeNull(); + todoItemInDatabase.Owner.Should().NotBeNull(); todoItemInDatabase.Owner.Id.Should().Be(newOwnerId); todoItemInDatabase.Assignee.Should().BeNull(); - todoItemInDatabase.Tags.ShouldHaveCount(1); + todoItemInDatabase.Tags.Should().HaveCount(1); todoItemInDatabase.Tags.ElementAt(0).Id.Should().Be(newTagId); }); - store.SqlCommands.ShouldHaveCount(15); + store.SqlCommands.Should().HaveCount(15); store.SqlCommands[0].With(command => { @@ -220,7 +220,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => RETURNING "Id" """)); - command.Parameters.ShouldHaveCount(3); + command.Parameters.Should().HaveCount(3); command.Parameters.Should().Contain("@p1", newOwner.FirstName); command.Parameters.Should().Contain("@p2", newOwner.LastName); command.Parameters.Should().Contain("@p3", null); @@ -234,7 +234,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", newOwnerId); }); @@ -246,7 +246,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => RETURNING "Id" """)); - command.Parameters.ShouldHaveCount(3); + command.Parameters.Should().HaveCount(3); command.Parameters.Should().Contain("@p1", newAssignee.FirstName); command.Parameters.Should().Contain("@p2", newAssignee.LastName); command.Parameters.Should().Contain("@p3", null); @@ -260,7 +260,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", newAssigneeId); }); @@ -272,7 +272,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => RETURNING "Id" """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", newTag.Name); command.Parameters.Should().Contain("@p2", null); }); @@ -285,7 +285,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", newTagId); }); @@ -297,7 +297,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => RETURNING "Id" """)); - command.Parameters.ShouldHaveCount(7); + command.Parameters.Should().HaveCount(7); command.Parameters.Should().Contain("@p1", newTodoItem.Description); command.Parameters.Should().Contain("@p2", newTodoItem.Priority); command.Parameters.Should().Contain("@p3", newTodoItem.DurationInHours); @@ -315,7 +315,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", newTodoItemId); }); @@ -328,7 +328,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", newTodoItemId); }); @@ -340,7 +340,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", newAssigneeId); command.Parameters.Should().Contain("@p2", newTodoItemId); }); @@ -354,7 +354,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", newTodoItemId); }); @@ -366,7 +366,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", DapperTestContext.FrozenTime); command.Parameters.Should().Contain("@p2", newTodoItemId); }); @@ -379,7 +379,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", newTodoItemId); command.Parameters.Should().Contain("@p2", newTagId); }); @@ -392,7 +392,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", newTodoItemId); }); @@ -403,7 +403,7 @@ DELETE FROM "People" WHERE "Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", newAssigneeId); }); } @@ -415,16 +415,13 @@ public async Task Can_rollback_on_error() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person newPerson = _fakers.Person.Generate(); + Person newPerson = _fakers.Person.GenerateOne(); const long unknownTodoItemId = Unknown.TypedId.Int64; const string personLocalId = "new-person"; - await _testContext.RunOnDatabaseAsync(async dbContext => - { - await _testContext.ClearAllTablesAsync(dbContext); - }); + await _testContext.RunOnDatabaseAsync(_testContext.ClearAllTablesAsync); var requestBody = new { @@ -472,13 +469,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); error.Title.Should().Be("A related resource does not exist."); error.Detail.Should().Be($"Related resource of type 'todoItems' with ID '{unknownTodoItemId}' in relationship 'assignedTodoItems' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[1]"); await _testContext.RunOnDatabaseAsync(async dbContext => @@ -487,7 +484,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => peopleInDatabase.Should().BeEmpty(); }); - store.SqlCommands.ShouldHaveCount(5); + store.SqlCommands.Should().HaveCount(5); store.SqlCommands[0].With(command => { @@ -497,7 +494,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => RETURNING "Id" """)); - command.Parameters.ShouldHaveCount(3); + command.Parameters.Should().HaveCount(3); command.Parameters.Should().Contain("@p1", null); command.Parameters.Should().Contain("@p2", newPerson.LastName); command.Parameters.Should().Contain("@p3", null); @@ -511,8 +508,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); - command.Parameters.ShouldContainKey("@p1").With(value => value.ShouldNotBeNull()); + command.Parameters.Should().HaveCount(1); + command.Parameters.Should().ContainKey("@p1").WhoseValue.Should().NotBeNull(); }); store.SqlCommands[2].With(command => @@ -524,8 +521,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); - command.Parameters.ShouldContainKey("@p1").With(value => value.ShouldNotBeNull()); + command.Parameters.Should().HaveCount(1); + command.Parameters.Should().ContainKey("@p1").WhoseValue.Should().NotBeNull(); }); store.SqlCommands[3].With(command => @@ -536,8 +533,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" = @p2 """)); - command.Parameters.ShouldHaveCount(2); - command.Parameters.ShouldContainKey("@p1").With(value => value.ShouldNotBeNull()); + command.Parameters.Should().HaveCount(2); + command.Parameters.Should().ContainKey("@p1").WhoseValue.Should().NotBeNull(); command.Parameters.Should().Contain("@p2", unknownTodoItemId); }); @@ -549,7 +546,7 @@ SELECT t1."Id" WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", unknownTodoItemId); }); } diff --git a/test/DapperTests/IntegrationTests/DapperTestContext.cs b/test/DapperTests/IntegrationTests/DapperTestContext.cs index 5817db099a..2156902f98 100644 --- a/test/DapperTests/IntegrationTests/DapperTestContext.cs +++ b/test/DapperTests/IntegrationTests/DapperTestContext.cs @@ -4,8 +4,6 @@ using DapperExample.Models; using DapperExample.Repositories; using DapperExample.TranslationToSql.DataModel; -using FluentAssertions.Common; -using FluentAssertions.Extensions; using JetBrains.Annotations; using JsonApiDotNetCore.Configuration; using Microsoft.AspNetCore.Hosting; @@ -13,10 +11,10 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging; using TestBuildingBlocks; using Xunit.Abstractions; -using IClock = DapperExample.IClock; namespace DapperTests.IntegrationTests; @@ -29,7 +27,7 @@ public sealed class DapperTestContext : IntegrationTest EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'; """; - public static readonly DateTimeOffset FrozenTime = 29.September(2018).At(16, 41, 56).AsUtc().ToDateTimeOffset(); + public static readonly DateTimeOffset FrozenTime = DefaultDateTimeUtc; private readonly Lazy> _lazyFactory; private ITestOutputHelper? _testOutputHelper; @@ -52,7 +50,10 @@ public DapperTestContext() private WebApplicationFactory CreateFactory() { +#pragma warning disable CA2000 // Dispose objects before losing scope + // Justification: The child factory returned by WithWebHostBuilder() is owned by the parent factory, which disposes it. return new WebApplicationFactory().WithWebHostBuilder(builder => +#pragma warning restore CA2000 // Dispose objects before losing scope { builder.UseSetting("ConnectionStrings:DapperExamplePostgreSql", $"Host=localhost;Database=DapperExample-{Guid.NewGuid():N};User ID=postgres;Password=postgres;Include Error Detail=true"); @@ -79,10 +80,7 @@ private WebApplicationFactory CreateFactory() builder.ConfigureServices(services => { - services.AddSingleton(new FrozenClock - { - UtcNow = FrozenTime - }); + services.Replace(ServiceDescriptor.Singleton(new FrozenTimeProvider(FrozenTime))); ServiceDescriptor scopedCaptureStore = services.Single(descriptor => descriptor.ImplementationType == typeof(SqlCaptureStore)); services.Remove(scopedCaptureStore); diff --git a/test/DapperTests/IntegrationTests/FrozenClock.cs b/test/DapperTests/IntegrationTests/FrozenClock.cs deleted file mode 100644 index 7edfadce5b..0000000000 --- a/test/DapperTests/IntegrationTests/FrozenClock.cs +++ /dev/null @@ -1,11 +0,0 @@ -using DapperExample; -using JetBrains.Annotations; -using TestBuildingBlocks; - -namespace DapperTests.IntegrationTests; - -[UsedImplicitly(ImplicitUseTargetFlags.Members)] -internal sealed class FrozenClock : IClock -{ - public DateTimeOffset UtcNow { get; set; } = FrozenSystemClock.DefaultDateTimeOffsetUtc; -} diff --git a/test/DapperTests/IntegrationTests/QueryStrings/FilterTests.cs b/test/DapperTests/IntegrationTests/QueryStrings/FilterTests.cs index 56bfdd5a7c..f7da3533f9 100644 --- a/test/DapperTests/IntegrationTests/QueryStrings/FilterTests.cs +++ b/test/DapperTests/IntegrationTests/QueryStrings/FilterTests.cs @@ -28,8 +28,8 @@ public async Task Can_filter_equals_on_obfuscated_id_at_primary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List tags = _fakers.Tag.Generate(3); - tags.ForEach(tag => tag.Color = _fakers.RgbColor.Generate()); + List tags = _fakers.Tag.GenerateList(3); + tags.ForEach(tag => tag.Color = _fakers.RgbColor.GenerateOne()); tags[0].Color!.StringId = "FF0000"; tags[1].Color!.StringId = "00FF00"; @@ -50,13 +50,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("tags"); responseDocument.Data.ManyValue[0].Id.Should().Be(tags[1].StringId); responseDocument.Meta.Should().ContainTotal(1); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -67,7 +67,7 @@ SELECT COUNT(*) WHERE t2."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", 0x00FF00); }); @@ -81,7 +81,7 @@ SELECT COUNT(*) ORDER BY t1."Id" """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", 0x00FF00); }); } @@ -93,8 +93,8 @@ public async Task Can_filter_any_on_obfuscated_id_at_primary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List tags = _fakers.Tag.Generate(3); - tags.ForEach(tag => tag.Color = _fakers.RgbColor.Generate()); + List tags = _fakers.Tag.GenerateList(3); + tags.ForEach(tag => tag.Color = _fakers.RgbColor.GenerateOne()); tags[0].Color!.StringId = "FF0000"; tags[1].Color!.StringId = "00FF00"; @@ -115,13 +115,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("tags"); responseDocument.Data.ManyValue[0].Id.Should().Be(tags[1].StringId); responseDocument.Meta.Should().ContainTotal(1); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -132,7 +132,7 @@ SELECT COUNT(*) WHERE t2."Id" IN (@p1, @p2) """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", 0x00FF00); command.Parameters.Should().Contain("@p2", 0x11EE11); }); @@ -147,7 +147,7 @@ SELECT COUNT(*) ORDER BY t1."Id" """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", 0x00FF00); command.Parameters.Should().Contain("@p2", 0x11EE11); }); @@ -160,9 +160,9 @@ public async Task Can_filter_equals_null_on_relationship_at_secondary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); - person.OwnedTodoItems = _fakers.TodoItem.Generate(2).ToHashSet(); - person.OwnedTodoItems.ElementAt(0).Assignee = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); + person.OwnedTodoItems = _fakers.TodoItem.GenerateSet(2); + person.OwnedTodoItems.ElementAt(0).Assignee = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -178,13 +178,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("todoItems"); responseDocument.Data.ManyValue[0].Id.Should().Be(person.OwnedTodoItems.ElementAt(1).StringId); responseDocument.Meta.Should().ContainTotal(1); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -196,7 +196,7 @@ SELECT COUNT(*) WHERE (t2."Id" = @p1) AND (t3."Id" IS NULL) """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", person.Id); }); @@ -215,7 +215,7 @@ WHERE t3."Id" IS NULL ORDER BY t4."Priority", t4."LastModifiedAt" DESC """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", person.Id); }); } @@ -227,8 +227,8 @@ public async Task Can_filter_equals_null_on_attribute_at_secondary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); - person.OwnedTodoItems = _fakers.TodoItem.Generate(2).ToHashSet(); + Person person = _fakers.Person.GenerateOne(); + person.OwnedTodoItems = _fakers.TodoItem.GenerateSet(2); person.OwnedTodoItems.ElementAt(1).DurationInHours = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -245,13 +245,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("todoItems"); responseDocument.Data.ManyValue[0].Id.Should().Be(person.OwnedTodoItems.ElementAt(1).StringId); responseDocument.Meta.Should().ContainTotal(1); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -262,7 +262,7 @@ SELECT COUNT(*) WHERE (t2."Id" = @p1) AND (t1."DurationInHours" IS NULL) """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", person.Id); }); @@ -280,7 +280,7 @@ WHERE t2."DurationInHours" IS NULL ORDER BY t3."Priority", t3."LastModifiedAt" DESC """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", person.Id); }); } @@ -292,8 +292,8 @@ public async Task Can_filter_equals_on_enum_attribute_at_primary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(3); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List todoItems = _fakers.TodoItem.GenerateList(3); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); todoItems.ForEach(todoItem => todoItem.Priority = TodoItemPriority.Low); todoItems[1].Priority = TodoItemPriority.Medium; @@ -313,13 +313,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("todoItems"); responseDocument.Data.ManyValue[0].Id.Should().Be(todoItems[1].StringId); responseDocument.Meta.Should().ContainTotal(1); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -329,7 +329,7 @@ SELECT COUNT(*) WHERE t1."Priority" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", todoItems[1].Priority); }); @@ -342,7 +342,7 @@ SELECT COUNT(*) ORDER BY t1."Priority", t1."LastModifiedAt" DESC """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", todoItems[1].Priority); }); } @@ -354,9 +354,9 @@ public async Task Can_filter_equals_on_string_attribute_at_secondary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); - person.AssignedTodoItems = _fakers.TodoItem.Generate(2).ToHashSet(); - person.AssignedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + Person person = _fakers.Person.GenerateOne(); + person.AssignedTodoItems = _fakers.TodoItem.GenerateSet(2); + person.AssignedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); person.AssignedTodoItems.ElementAt(1).Description = "Take exam"; @@ -375,13 +375,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("todoItems"); responseDocument.Data.ManyValue[0].Id.Should().Be(person.AssignedTodoItems.ElementAt(1).StringId); responseDocument.Meta.Should().ContainTotal(1); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -392,7 +392,7 @@ SELECT COUNT(*) WHERE (t2."Id" = @p1) AND (t1."Description" = @p2) """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", person.Id); command.Parameters.Should().Contain("@p2", person.AssignedTodoItems.ElementAt(1).Description); }); @@ -411,7 +411,7 @@ LEFT JOIN ( ORDER BY t3."Priority", t3."LastModifiedAt" DESC """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", person.Id); command.Parameters.Should().Contain("@p2", person.AssignedTodoItems.ElementAt(1).Description); }); @@ -424,9 +424,9 @@ public async Task Can_filter_equality_on_attributes_at_primary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(2); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); - todoItems.ForEach(todoItem => todoItem.Assignee = _fakers.Person.Generate()); + List todoItems = _fakers.TodoItem.GenerateList(2); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); + todoItems.ForEach(todoItem => todoItem.Assignee = _fakers.Person.GenerateOne()); todoItems[1].Assignee!.FirstName = todoItems[1].Assignee!.LastName; @@ -445,13 +445,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("todoItems"); responseDocument.Data.ManyValue[0].Id.Should().Be(todoItems[1].StringId); responseDocument.Meta.Should().ContainTotal(1); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -486,8 +486,8 @@ public async Task Can_filter_any_with_single_constant_at_secondary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); - person.OwnedTodoItems = _fakers.TodoItem.Generate(2).ToHashSet(); + Person person = _fakers.Person.GenerateOne(); + person.OwnedTodoItems = _fakers.TodoItem.GenerateSet(2); person.OwnedTodoItems.ElementAt(0).Priority = TodoItemPriority.Low; person.OwnedTodoItems.ElementAt(1).Priority = TodoItemPriority.Medium; @@ -506,13 +506,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("todoItems"); responseDocument.Data.ManyValue[0].Id.Should().Be(person.OwnedTodoItems.ElementAt(1).StringId); responseDocument.Meta.Should().ContainTotal(1); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -523,7 +523,7 @@ SELECT COUNT(*) WHERE (t2."Id" = @p1) AND (t1."Priority" = @p2) """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", person.Id); command.Parameters.Should().Contain("@p2", TodoItemPriority.Medium); }); @@ -542,7 +542,7 @@ LEFT JOIN ( ORDER BY t3."Priority", t3."LastModifiedAt" DESC """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", person.Id); command.Parameters.Should().Contain("@p2", TodoItemPriority.Medium); }); @@ -555,9 +555,9 @@ public async Task Can_filter_not_not_not_not_equals_on_string_attribute_at_prima var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); todoItem.Description = "X"; - todoItem.Owner = _fakers.Person.Generate(); + todoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -574,13 +574,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("todoItems"); responseDocument.Data.ManyValue[0].Id.Should().Be(todoItem.StringId); responseDocument.Meta.Should().ContainTotal(1); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -590,7 +590,7 @@ SELECT COUNT(*) WHERE t1."Description" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", "X"); }); @@ -603,7 +603,7 @@ SELECT COUNT(*) ORDER BY t1."Priority", t1."LastModifiedAt" DESC """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", "X"); }); } @@ -615,7 +615,7 @@ public async Task Can_filter_not_equals_on_nullable_attribute_at_primary_endpoin var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List people = _fakers.Person.Generate(3); + List people = _fakers.Person.GenerateList(3); people[0].FirstName = "X"; people[1].FirstName = null; people[2].FirstName = "Y"; @@ -635,14 +635,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue.Should().AllSatisfy(resource => resource.Type.Should().Be("people")); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Id == people[1].StringId); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Id == people[2].StringId); responseDocument.Meta.Should().ContainTotal(2); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -652,7 +652,7 @@ SELECT COUNT(*) WHERE (NOT (t1."FirstName" = @p1)) OR (t1."FirstName" IS NULL) """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", "X"); }); @@ -665,7 +665,7 @@ SELECT COUNT(*) ORDER BY t1."Id" """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", "X"); }); } @@ -677,10 +677,10 @@ public async Task Can_filter_not_equals_on_attributes_of_optional_relationship_a var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(2); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List todoItems = _fakers.TodoItem.GenerateList(2); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); - todoItems[1].Assignee = _fakers.Person.Generate(); + todoItems[1].Assignee = _fakers.Person.GenerateOne(); todoItems[1].Assignee!.FirstName = "X"; todoItems[1].Assignee!.LastName = "Y"; @@ -699,13 +699,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("todoItems"); responseDocument.Data.ManyValue[0].Id.Should().Be(todoItems[0].StringId); responseDocument.Meta.Should().ContainTotal(1); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -716,7 +716,7 @@ SELECT COUNT(*) WHERE (NOT ((t2."FirstName" = @p1) AND (t2."LastName" = @p2))) OR (t2."FirstName" IS NULL) OR (t2."LastName" IS NULL) """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", "X"); command.Parameters.Should().Contain("@p2", "Y"); }); @@ -731,7 +731,7 @@ SELECT COUNT(*) ORDER BY t1."Priority", t1."LastModifiedAt" DESC """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", "X"); command.Parameters.Should().Contain("@p2", "Y"); }); @@ -744,8 +744,8 @@ public async Task Can_filter_text_at_primary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(3); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List todoItems = _fakers.TodoItem.GenerateList(3); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); todoItems[0].Description = "One"; todoItems[1].Description = "Two"; @@ -768,13 +768,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("todoItems"); responseDocument.Data.ManyValue[0].Id.Should().Be(todoItems[1].StringId); responseDocument.Meta.Should().ContainTotal(1); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -785,7 +785,7 @@ SELECT COUNT(*) WHERE (t1."Description" LIKE 'T%') AND (NOT (t1."Description" IN (@p1, @p2))) AND (t2."FirstName" = @p3) AND (t1."Description" LIKE '%o%') """)); - command.Parameters.ShouldHaveCount(3); + command.Parameters.Should().HaveCount(3); command.Parameters.Should().Contain("@p1", "Four"); command.Parameters.Should().Contain("@p2", "Three"); command.Parameters.Should().Contain("@p3", "Jack"); @@ -801,7 +801,7 @@ SELECT COUNT(*) ORDER BY t1."Priority", t1."LastModifiedAt" DESC """)); - command.Parameters.ShouldHaveCount(3); + command.Parameters.Should().HaveCount(3); command.Parameters.Should().Contain("@p1", "Four"); command.Parameters.Should().Contain("@p2", "Three"); command.Parameters.Should().Contain("@p3", "Jack"); @@ -815,7 +815,7 @@ public async Task Can_filter_special_characters_in_text_at_primary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List tags = _fakers.Tag.Generate(6); + List tags = _fakers.Tag.GenerateList(6); tags[0].Name = "A%Z"; tags[1].Name = "A_Z"; tags[2].Name = @"A\Z"; @@ -838,7 +838,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(5); + responseDocument.Data.ManyValue.Should().HaveCount(5); responseDocument.Data.ManyValue.Should().AllSatisfy(resource => resource.Type.Should().Be("tags")); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Id == tags[0].StringId); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Id == tags[1].StringId); @@ -848,7 +848,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Meta.Should().ContainTotal(5); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -881,8 +881,8 @@ public async Task Can_filter_numeric_range_at_primary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(3); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List todoItems = _fakers.TodoItem.GenerateList(3); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); todoItems[0].DurationInHours = 100; todoItems[1].DurationInHours = 200; @@ -903,14 +903,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue.Should().AllSatisfy(resource => resource.Type.Should().Be("todoItems")); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Id == todoItems[0].StringId); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Id == todoItems[2].StringId); responseDocument.Meta.Should().ContainTotal(2); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -920,7 +920,7 @@ SELECT COUNT(*) WHERE (t1."DurationInHours" > @p1) OR (t1."DurationInHours" <= @p2) """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", 250); command.Parameters.Should().Contain("@p2", 100); }); @@ -934,7 +934,7 @@ SELECT COUNT(*) ORDER BY t1."Priority", t1."LastModifiedAt" DESC """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", 250); command.Parameters.Should().Contain("@p2", 100); }); @@ -947,11 +947,11 @@ public async Task Can_filter_count_at_primary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(2); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List todoItems = _fakers.TodoItem.GenerateList(2); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); - todoItems[1].Owner.AssignedTodoItems = _fakers.TodoItem.Generate(2).ToHashSet(); - todoItems[1].Owner.AssignedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + todoItems[1].Owner.AssignedTodoItems = _fakers.TodoItem.GenerateSet(2); + todoItems[1].Owner.AssignedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -968,13 +968,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("todoItems"); responseDocument.Data.ManyValue[0].Id.Should().Be(todoItems[1].StringId); responseDocument.Meta.Should().ContainTotal(1); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -990,7 +990,7 @@ SELECT COUNT(*) ) > @p1) AND (NOT (t4."Id" IS NULL)) """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", 1); }); @@ -1009,7 +1009,7 @@ SELECT COUNT(*) ORDER BY t1."Priority", t1."LastModifiedAt" DESC """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", 1); }); } @@ -1021,17 +1021,17 @@ public async Task Can_filter_nested_conditional_has_at_primary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(2); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List todoItems = _fakers.TodoItem.GenerateList(2); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); - todoItems[1].Owner.AssignedTodoItems = _fakers.TodoItem.Generate(2).ToHashSet(); + todoItems[1].Owner.AssignedTodoItems = _fakers.TodoItem.GenerateSet(2); todoItems[1].Owner.AssignedTodoItems.ForEach(todoItem => { todoItem.Description = "Homework"; - todoItem.Owner = _fakers.Person.Generate(); + todoItem.Owner = _fakers.Person.GenerateOne(); todoItem.Owner.LastName = "Smith"; - todoItem.Tags = _fakers.Tag.Generate(1).ToHashSet(); + todoItem.Tags = _fakers.Tag.GenerateSet(1); }); todoItems[1].Owner.AssignedTodoItems.ElementAt(1).Tags.ElementAt(0).Name = "Personal"; @@ -1052,13 +1052,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("todoItems"); responseDocument.Data.ManyValue[0].Id.Should().Be(todoItems[1].StringId); responseDocument.Meta.Should().ContainTotal(1); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -1078,7 +1078,7 @@ SELECT 1 ) """)); - command.Parameters.ShouldHaveCount(3); + command.Parameters.Should().HaveCount(3); command.Parameters.Should().Contain("@p1", "Personal"); command.Parameters.Should().Contain("@p2", "Smith"); command.Parameters.Should().Contain("@p3", "Homework"); @@ -1103,7 +1103,7 @@ SELECT 1 ORDER BY t1."Priority", t1."LastModifiedAt" DESC """)); - command.Parameters.ShouldHaveCount(3); + command.Parameters.Should().HaveCount(3); command.Parameters.Should().Contain("@p1", "Personal"); command.Parameters.Should().Contain("@p2", "Smith"); command.Parameters.Should().Contain("@p3", "Homework"); @@ -1117,14 +1117,14 @@ public async Task Can_filter_conditional_has_with_null_check_at_primary_endpoint var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List people = _fakers.Person.Generate(3); - people.ForEach(person => person.OwnedTodoItems = _fakers.TodoItem.Generate(1).ToHashSet()); + List people = _fakers.Person.GenerateList(3); + people.ForEach(person => person.OwnedTodoItems = _fakers.TodoItem.GenerateSet(1)); people[0].OwnedTodoItems.ElementAt(0).Assignee = null; - people[1].OwnedTodoItems.ElementAt(0).Assignee = _fakers.Person.Generate(); + people[1].OwnedTodoItems.ElementAt(0).Assignee = _fakers.Person.GenerateOne(); - people[2].OwnedTodoItems.ElementAt(0).Assignee = _fakers.Person.Generate(); + people[2].OwnedTodoItems.ElementAt(0).Assignee = _fakers.Person.GenerateOne(); people[2].OwnedTodoItems.ElementAt(0).Assignee!.FirstName = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -1142,13 +1142,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("people"); responseDocument.Data.ManyValue[0].Id.Should().Be(people[2].StringId); responseDocument.Meta.Should().ContainTotal(1); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -1191,8 +1191,8 @@ public async Task Can_filter_using_logical_operators_at_primary_endpoint() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(5); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List todoItems = _fakers.TodoItem.GenerateList(5); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); todoItems[0].Description = "0"; todoItems[0].Priority = TodoItemPriority.High; @@ -1229,7 +1229,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(3); + responseDocument.Data.ManyValue.Should().HaveCount(3); responseDocument.Data.ManyValue.Should().AllSatisfy(resource => resource.Type.Should().Be("todoItems")); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Id == todoItems[2].StringId); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Id == todoItems[3].StringId); @@ -1237,7 +1237,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Meta.Should().ContainTotal(3); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -1247,7 +1247,7 @@ SELECT COUNT(*) WHERE (t1."Description" = @p1) AND ((t1."Priority" = @p2) OR (t1."DurationInHours" = @p3)) """)); - command.Parameters.ShouldHaveCount(3); + command.Parameters.Should().HaveCount(3); command.Parameters.Should().Contain("@p1", "1"); command.Parameters.Should().Contain("@p2", TodoItemPriority.High); command.Parameters.Should().Contain("@p3", 1); @@ -1262,7 +1262,7 @@ SELECT COUNT(*) ORDER BY t1."Priority", t1."LastModifiedAt" DESC """)); - command.Parameters.ShouldHaveCount(3); + command.Parameters.Should().HaveCount(3); command.Parameters.Should().Contain("@p1", "1"); command.Parameters.Should().Contain("@p2", TodoItemPriority.High); command.Parameters.Should().Contain("@p3", 1); @@ -1276,7 +1276,7 @@ public async Task Cannot_filter_on_unmapped_attribute() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1292,7 +1292,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); diff --git a/test/DapperTests/IntegrationTests/QueryStrings/IncludeTests.cs b/test/DapperTests/IntegrationTests/QueryStrings/IncludeTests.cs index 09d307a256..77805ee1b5 100644 --- a/test/DapperTests/IntegrationTests/QueryStrings/IncludeTests.cs +++ b/test/DapperTests/IntegrationTests/QueryStrings/IncludeTests.cs @@ -28,12 +28,12 @@ public async Task Can_get_primary_resources_with_multiple_include_chains() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person owner = _fakers.Person.Generate(); + Person owner = _fakers.Person.GenerateOne(); - List todoItems = _fakers.TodoItem.Generate(2); + List todoItems = _fakers.TodoItem.GenerateList(2); todoItems.ForEach(todoItem => todoItem.Owner = owner); - todoItems.ForEach(todoItem => todoItem.Tags = _fakers.Tag.Generate(2).ToHashSet()); - todoItems[1].Assignee = _fakers.Person.Generate(); + todoItems.ForEach(todoItem => todoItem.Tags = _fakers.Tag.GenerateSet(2)); + todoItems[1].Assignee = _fakers.Person.GenerateOne(); todoItems[0].Priority = TodoItemPriority.High; todoItems[1].Priority = TodoItemPriority.Low; @@ -53,31 +53,31 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue.Should().AllSatisfy(resource => resource.Type.Should().Be("todoItems")); responseDocument.Data.ManyValue[0].Id.Should().Be(todoItems[0].StringId); responseDocument.Data.ManyValue[0].Relationships.With(relationships => { - relationships.ShouldContainKey("owner").With(value => + relationships.Should().ContainKey("owner").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.SingleValue.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Data.SingleValue.Should().NotBeNull(); value.Data.SingleValue.Type.Should().Be("people"); value.Data.SingleValue.Id.Should().Be(todoItems[0].Owner.StringId); }); - relationships.ShouldContainKey("assignee").With(value => + relationships.Should().ContainKey("assignee").WhoseValue.With(value => { - value.ShouldNotBeNull(); + value.Should().NotBeNull(); value.Data.SingleValue.Should().BeNull(); }); - relationships.ShouldContainKey("tags").With(value => + relationships.Should().ContainKey("tags").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.ManyValue.ShouldHaveCount(2); + value.Should().NotBeNull(); + value.Data.ManyValue.Should().HaveCount(2); value.Data.ManyValue.Should().AllSatisfy(resource => resource.Type.Should().Be("tags")); value.Data.ManyValue[0].Id.Should().Be(todoItems[0].Tags.ElementAt(0).StringId); value.Data.ManyValue[1].Id.Should().Be(todoItems[0].Tags.ElementAt(1).StringId); @@ -88,63 +88,63 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Data.ManyValue[1].Relationships.With(relationships => { - relationships.ShouldContainKey("owner").With(value => + relationships.Should().ContainKey("owner").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.SingleValue.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Data.SingleValue.Should().NotBeNull(); value.Data.SingleValue.Type.Should().Be("people"); value.Data.SingleValue.Id.Should().Be(todoItems[1].Owner.StringId); }); - relationships.ShouldContainKey("assignee").With(value => + relationships.Should().ContainKey("assignee").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.SingleValue.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Data.SingleValue.Should().NotBeNull(); value.Data.SingleValue.Type.Should().Be("people"); value.Data.SingleValue.Id.Should().Be(todoItems[1].Assignee!.StringId); }); - relationships.ShouldContainKey("tags").With(value => + relationships.Should().ContainKey("tags").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.ManyValue.ShouldHaveCount(2); + value.Should().NotBeNull(); + value.Data.ManyValue.Should().HaveCount(2); value.Data.ManyValue.Should().AllSatisfy(resource => resource.Type.Should().Be("tags")); value.Data.ManyValue[0].Id.Should().Be(todoItems[1].Tags.ElementAt(0).StringId); value.Data.ManyValue[1].Id.Should().Be(todoItems[1].Tags.ElementAt(1).StringId); }); }); - responseDocument.Included.ShouldHaveCount(6); + responseDocument.Included.Should().HaveCount(6); responseDocument.Included[0].Type.Should().Be("people"); responseDocument.Included[0].Id.Should().Be(owner.StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("firstName").With(value => value.Should().Be(owner.FirstName)); - responseDocument.Included[0].Attributes.ShouldContainKey("lastName").With(value => value.Should().Be(owner.LastName)); + responseDocument.Included[0].Attributes.Should().ContainKey("firstName").WhoseValue.Should().Be(owner.FirstName); + responseDocument.Included[0].Attributes.Should().ContainKey("lastName").WhoseValue.Should().Be(owner.LastName); responseDocument.Included[1].Type.Should().Be("tags"); responseDocument.Included[1].Id.Should().Be(todoItems[0].Tags.ElementAt(0).StringId); - responseDocument.Included[1].Attributes.ShouldContainKey("name").With(value => value.Should().Be(todoItems[0].Tags.ElementAt(0).Name)); + responseDocument.Included[1].Attributes.Should().ContainKey("name").WhoseValue.Should().Be(todoItems[0].Tags.ElementAt(0).Name); responseDocument.Included[2].Type.Should().Be("tags"); responseDocument.Included[2].Id.Should().Be(todoItems[0].Tags.ElementAt(1).StringId); - responseDocument.Included[2].Attributes.ShouldContainKey("name").With(value => value.Should().Be(todoItems[0].Tags.ElementAt(1).Name)); + responseDocument.Included[2].Attributes.Should().ContainKey("name").WhoseValue.Should().Be(todoItems[0].Tags.ElementAt(1).Name); responseDocument.Included[3].Type.Should().Be("people"); responseDocument.Included[3].Id.Should().Be(todoItems[1].Assignee!.StringId); - responseDocument.Included[3].Attributes.ShouldContainKey("firstName").With(value => value.Should().Be(todoItems[1].Assignee!.FirstName)); - responseDocument.Included[3].Attributes.ShouldContainKey("lastName").With(value => value.Should().Be(todoItems[1].Assignee!.LastName)); + responseDocument.Included[3].Attributes.Should().ContainKey("firstName").WhoseValue.Should().Be(todoItems[1].Assignee!.FirstName); + responseDocument.Included[3].Attributes.Should().ContainKey("lastName").WhoseValue.Should().Be(todoItems[1].Assignee!.LastName); responseDocument.Included[4].Type.Should().Be("tags"); responseDocument.Included[4].Id.Should().Be(todoItems[1].Tags.ElementAt(0).StringId); - responseDocument.Included[4].Attributes.ShouldContainKey("name").With(value => value.Should().Be(todoItems[1].Tags.ElementAt(0).Name)); + responseDocument.Included[4].Attributes.Should().ContainKey("name").WhoseValue.Should().Be(todoItems[1].Tags.ElementAt(0).Name); responseDocument.Included[5].Type.Should().Be("tags"); responseDocument.Included[5].Id.Should().Be(todoItems[1].Tags.ElementAt(1).StringId); - responseDocument.Included[5].Attributes.ShouldContainKey("name").With(value => value.Should().Be(todoItems[1].Tags.ElementAt(1).Name)); + responseDocument.Included[5].Attributes.Should().ContainKey("name").WhoseValue.Should().Be(todoItems[1].Tags.ElementAt(1).Name); responseDocument.Meta.Should().ContainTotal(2); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -179,10 +179,10 @@ public async Task Can_get_primary_resources_with_includes() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(25); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); - todoItems.ForEach(todoItem => todoItem.Tags = _fakers.Tag.Generate(15).ToHashSet()); - todoItems.ForEach(todoItem => todoItem.Tags.ForEach(tag => tag.Color = _fakers.RgbColor.Generate())); + List todoItems = _fakers.TodoItem.GenerateList(25); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); + todoItems.ForEach(todoItem => todoItem.Tags = _fakers.Tag.GenerateSet(15)); + todoItems.ForEach(todoItem => todoItem.Tags.ForEach(tag => tag.Color = _fakers.RgbColor.GenerateOne())); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -199,20 +199,20 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(25); + responseDocument.Data.ManyValue.Should().HaveCount(25); responseDocument.Data.ManyValue.ForEach(resource => { resource.Type.Should().Be("todoItems"); - resource.Attributes.ShouldOnlyContainKeys("description", "priority", "durationInHours", "createdAt", "modifiedAt"); - resource.Relationships.ShouldOnlyContainKeys("owner", "assignee", "tags"); + resource.Attributes.Should().OnlyContainKeys("description", "priority", "durationInHours", "createdAt", "modifiedAt"); + resource.Relationships.Should().OnlyContainKeys("owner", "assignee", "tags"); }); - responseDocument.Included.ShouldHaveCount(25 * 15 * 2); + responseDocument.Included.Should().HaveCount(25 * 15 * 2); responseDocument.Meta.Should().ContainTotal(25); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { diff --git a/test/DapperTests/IntegrationTests/QueryStrings/PaginationTests.cs b/test/DapperTests/IntegrationTests/QueryStrings/PaginationTests.cs index 137ba693f0..854fb176db 100644 --- a/test/DapperTests/IntegrationTests/QueryStrings/PaginationTests.cs +++ b/test/DapperTests/IntegrationTests/QueryStrings/PaginationTests.cs @@ -23,8 +23,8 @@ public PaginationTests(DapperTestContext testContext, ITestOutputHelper testOutp public async Task Cannot_use_pagination() { // Arrange - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -41,7 +41,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.InternalServerError); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.InternalServerError); diff --git a/test/DapperTests/IntegrationTests/QueryStrings/SortTests.cs b/test/DapperTests/IntegrationTests/QueryStrings/SortTests.cs index 33643519ce..488dda2cc3 100644 --- a/test/DapperTests/IntegrationTests/QueryStrings/SortTests.cs +++ b/test/DapperTests/IntegrationTests/QueryStrings/SortTests.cs @@ -28,8 +28,8 @@ public async Task Can_sort_on_attributes_in_primary_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(3); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List todoItems = _fakers.TodoItem.GenerateList(3); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); todoItems[0].Description = "B"; todoItems[1].Description = "A"; @@ -50,13 +50,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(3); + responseDocument.Data.ManyValue.Should().HaveCount(3); responseDocument.Data.ManyValue.Should().AllSatisfy(resource => resource.Type.Should().Be("todoItems")); responseDocument.Data.ManyValue[0].Id.Should().Be(todoItems[2].StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(todoItems[0].StringId); responseDocument.Data.ManyValue[2].Id.Should().Be(todoItems[1].StringId); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -87,14 +87,14 @@ public async Task Can_sort_on_attributes_in_secondary_and_included_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); - person.OwnedTodoItems = _fakers.TodoItem.Generate(3).ToHashSet(); + Person person = _fakers.Person.GenerateOne(); + person.OwnedTodoItems = _fakers.TodoItem.GenerateSet(3); person.OwnedTodoItems.ElementAt(0).DurationInHours = 40; person.OwnedTodoItems.ElementAt(1).DurationInHours = 100; person.OwnedTodoItems.ElementAt(2).DurationInHours = 250; - person.OwnedTodoItems.ElementAt(1).Tags = _fakers.Tag.Generate(2).ToHashSet(); + person.OwnedTodoItems.ElementAt(1).Tags = _fakers.Tag.GenerateSet(2); person.OwnedTodoItems.ElementAt(1).Tags.ElementAt(0).Name = "B"; person.OwnedTodoItems.ElementAt(1).Tags.ElementAt(1).Name = "A"; @@ -113,18 +113,18 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(3); + responseDocument.Data.ManyValue.Should().HaveCount(3); responseDocument.Data.ManyValue.Should().AllSatisfy(resource => resource.Type.Should().Be("todoItems")); responseDocument.Data.ManyValue[0].Id.Should().Be(person.OwnedTodoItems.ElementAt(2).StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(person.OwnedTodoItems.ElementAt(1).StringId); responseDocument.Data.ManyValue[2].Id.Should().Be(person.OwnedTodoItems.ElementAt(0).StringId); - responseDocument.Included.ShouldHaveCount(2); + responseDocument.Included.Should().HaveCount(2); responseDocument.Included.Should().AllSatisfy(resource => resource.Type.Should().Be("tags")); responseDocument.Included[0].Id.Should().Be(person.OwnedTodoItems.ElementAt(1).Tags.ElementAt(1).StringId); responseDocument.Included[1].Id.Should().Be(person.OwnedTodoItems.ElementAt(1).Tags.ElementAt(0).StringId); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -135,7 +135,7 @@ SELECT COUNT(*) WHERE t2."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", person.Id); }); @@ -150,7 +150,7 @@ SELECT COUNT(*) ORDER BY t2."DurationInHours" DESC, t3."Name" """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", person.Id); }); } @@ -162,12 +162,12 @@ public async Task Can_sort_on_count_in_primary_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(3); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List todoItems = _fakers.TodoItem.GenerateList(3); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); - todoItems[0].Tags = _fakers.Tag.Generate(2).ToHashSet(); - todoItems[1].Tags = _fakers.Tag.Generate(1).ToHashSet(); - todoItems[2].Tags = _fakers.Tag.Generate(3).ToHashSet(); + todoItems[0].Tags = _fakers.Tag.GenerateSet(2); + todoItems[1].Tags = _fakers.Tag.GenerateSet(1); + todoItems[2].Tags = _fakers.Tag.GenerateSet(3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -184,13 +184,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(3); + responseDocument.Data.ManyValue.Should().HaveCount(3); responseDocument.Data.ManyValue.Should().AllSatisfy(resource => resource.Type.Should().Be("todoItems")); responseDocument.Data.ManyValue[0].Id.Should().Be(todoItems[2].StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(todoItems[0].StringId); responseDocument.Data.ManyValue[2].Id.Should().Be(todoItems[1].StringId); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -225,12 +225,12 @@ public async Task Can_sort_on_count_in_secondary_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); - person.OwnedTodoItems = _fakers.TodoItem.Generate(3).ToHashSet(); + Person person = _fakers.Person.GenerateOne(); + person.OwnedTodoItems = _fakers.TodoItem.GenerateSet(3); - person.OwnedTodoItems.ElementAt(0).Tags = _fakers.Tag.Generate(2).ToHashSet(); - person.OwnedTodoItems.ElementAt(1).Tags = _fakers.Tag.Generate(1).ToHashSet(); - person.OwnedTodoItems.ElementAt(2).Tags = _fakers.Tag.Generate(3).ToHashSet(); + person.OwnedTodoItems.ElementAt(0).Tags = _fakers.Tag.GenerateSet(2); + person.OwnedTodoItems.ElementAt(1).Tags = _fakers.Tag.GenerateSet(1); + person.OwnedTodoItems.ElementAt(2).Tags = _fakers.Tag.GenerateSet(3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -247,13 +247,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(3); + responseDocument.Data.ManyValue.Should().HaveCount(3); responseDocument.Data.ManyValue.Should().AllSatisfy(resource => resource.Type.Should().Be("todoItems")); responseDocument.Data.ManyValue[0].Id.Should().Be(person.OwnedTodoItems.ElementAt(2).StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(person.OwnedTodoItems.ElementAt(0).StringId); responseDocument.Data.ManyValue[2].Id.Should().Be(person.OwnedTodoItems.ElementAt(1).StringId); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -264,7 +264,7 @@ SELECT COUNT(*) WHERE t2."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", person.Id); }); @@ -282,7 +282,7 @@ SELECT COUNT(*) ) DESC, t2."Id" """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", person.Id); }); } @@ -294,12 +294,12 @@ public async Task Can_sort_on_count_in_secondary_resources_with_include() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); - person.OwnedTodoItems = _fakers.TodoItem.Generate(3).ToHashSet(); + Person person = _fakers.Person.GenerateOne(); + person.OwnedTodoItems = _fakers.TodoItem.GenerateSet(3); - person.OwnedTodoItems.ElementAt(0).Tags = _fakers.Tag.Generate(2).ToHashSet(); - person.OwnedTodoItems.ElementAt(1).Tags = _fakers.Tag.Generate(1).ToHashSet(); - person.OwnedTodoItems.ElementAt(2).Tags = _fakers.Tag.Generate(3).ToHashSet(); + person.OwnedTodoItems.ElementAt(0).Tags = _fakers.Tag.GenerateSet(2); + person.OwnedTodoItems.ElementAt(1).Tags = _fakers.Tag.GenerateSet(1); + person.OwnedTodoItems.ElementAt(2).Tags = _fakers.Tag.GenerateSet(3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -316,13 +316,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(3); + responseDocument.Data.ManyValue.Should().HaveCount(3); responseDocument.Data.ManyValue.Should().AllSatisfy(resource => resource.Type.Should().Be("todoItems")); responseDocument.Data.ManyValue[0].Id.Should().Be(person.OwnedTodoItems.ElementAt(2).StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(person.OwnedTodoItems.ElementAt(0).StringId); responseDocument.Data.ManyValue[2].Id.Should().Be(person.OwnedTodoItems.ElementAt(1).StringId); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -333,7 +333,7 @@ SELECT COUNT(*) WHERE t2."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", person.Id); }); @@ -352,7 +352,7 @@ SELECT COUNT(*) ) DESC, t2."Id", t4."Id" """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", person.Id); }); } @@ -364,12 +364,12 @@ public async Task Can_sort_on_count_in_included_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); - person.OwnedTodoItems = _fakers.TodoItem.Generate(4).ToHashSet(); + Person person = _fakers.Person.GenerateOne(); + person.OwnedTodoItems = _fakers.TodoItem.GenerateSet(4); - person.OwnedTodoItems.ElementAt(0).Tags = _fakers.Tag.Generate(2).ToHashSet(); - person.OwnedTodoItems.ElementAt(1).Tags = _fakers.Tag.Generate(1).ToHashSet(); - person.OwnedTodoItems.ElementAt(2).Tags = _fakers.Tag.Generate(3).ToHashSet(); + person.OwnedTodoItems.ElementAt(0).Tags = _fakers.Tag.GenerateSet(2); + person.OwnedTodoItems.ElementAt(1).Tags = _fakers.Tag.GenerateSet(1); + person.OwnedTodoItems.ElementAt(2).Tags = _fakers.Tag.GenerateSet(3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -386,18 +386,18 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("people"); responseDocument.Data.ManyValue[0].Id.Should().Be(person.StringId); - responseDocument.Included.ShouldHaveCount(4); + responseDocument.Included.Should().HaveCount(4); responseDocument.Included.Should().AllSatisfy(resource => resource.Type.Should().Be("todoItems")); responseDocument.Included[0].Id.Should().Be(person.OwnedTodoItems.ElementAt(2).StringId); responseDocument.Included[1].Id.Should().Be(person.OwnedTodoItems.ElementAt(0).StringId); responseDocument.Included[2].Id.Should().Be(person.OwnedTodoItems.ElementAt(1).StringId); responseDocument.Included[3].Id.Should().Be(person.OwnedTodoItems.ElementAt(3).StringId); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { diff --git a/test/DapperTests/IntegrationTests/QueryStrings/SparseFieldSets.cs b/test/DapperTests/IntegrationTests/QueryStrings/SparseFieldSets.cs index e66616810e..b2e0c68f8c 100644 --- a/test/DapperTests/IntegrationTests/QueryStrings/SparseFieldSets.cs +++ b/test/DapperTests/IntegrationTests/QueryStrings/SparseFieldSets.cs @@ -28,9 +28,9 @@ public async Task Can_select_fields_in_primary_and_included_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); - todoItem.Assignee = _fakers.Person.Generate(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); + todoItem.Assignee = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -47,44 +47,44 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("todoItems"); responseDocument.Data.ManyValue[0].Id.Should().Be(todoItem.StringId); - responseDocument.Data.ManyValue[0].Attributes.ShouldHaveCount(2); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("description").With(value => value.Should().Be(todoItem.Description)); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("durationInHours").With(value => value.Should().Be(todoItem.DurationInHours)); - responseDocument.Data.ManyValue[0].Relationships.ShouldHaveCount(2); + responseDocument.Data.ManyValue[0].Attributes.Should().HaveCount(2); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("description").WhoseValue.Should().Be(todoItem.Description); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("durationInHours").WhoseValue.Should().Be(todoItem.DurationInHours); + responseDocument.Data.ManyValue[0].Relationships.Should().HaveCount(2); - responseDocument.Data.ManyValue[0].Relationships.ShouldContainKey("owner").With(value => + responseDocument.Data.ManyValue[0].Relationships.Should().ContainKey("owner").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.SingleValue.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Data.SingleValue.Should().NotBeNull(); value.Data.SingleValue.Type.Should().Be("people"); value.Data.SingleValue.Id.Should().Be(todoItem.Owner.StringId); }); - responseDocument.Data.ManyValue[0].Relationships.ShouldContainKey("assignee").With(value => + responseDocument.Data.ManyValue[0].Relationships.Should().ContainKey("assignee").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.SingleValue.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Data.SingleValue.Should().NotBeNull(); value.Data.SingleValue.Type.Should().Be("people"); value.Data.SingleValue.Id.Should().Be(todoItem.Assignee.StringId); }); - responseDocument.Included.ShouldHaveCount(2); + responseDocument.Included.Should().HaveCount(2); responseDocument.Included.Should().AllSatisfy(resource => resource.Type.Should().Be("people")); responseDocument.Included[0].Id.Should().Be(todoItem.Owner.StringId); - responseDocument.Included[0].Attributes.ShouldHaveCount(1); - responseDocument.Included[0].Attributes.ShouldContainKey("lastName").With(value => value.Should().Be(todoItem.Owner.LastName)); + responseDocument.Included[0].Attributes.Should().HaveCount(1); + responseDocument.Included[0].Attributes.Should().ContainKey("lastName").WhoseValue.Should().Be(todoItem.Owner.LastName); responseDocument.Included[0].Relationships.Should().BeNull(); responseDocument.Included[1].Id.Should().Be(todoItem.Assignee.StringId); - responseDocument.Included[1].Attributes.ShouldHaveCount(1); - responseDocument.Included[1].Attributes.ShouldContainKey("lastName").With(value => value.Should().Be(todoItem.Assignee.LastName)); + responseDocument.Included[1].Attributes.Should().HaveCount(1); + responseDocument.Included[1].Attributes.Should().ContainKey("lastName").WhoseValue.Should().Be(todoItem.Assignee.LastName); responseDocument.Included[1].Relationships.Should().BeNull(); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -117,8 +117,8 @@ public async Task Can_select_attribute_in_primary_resource() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -134,14 +134,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("todoItems"); responseDocument.Data.SingleValue.Id.Should().Be(todoItem.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldHaveCount(1); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("description").With(value => value.Should().Be(todoItem.Description)); + responseDocument.Data.SingleValue.Attributes.Should().HaveCount(1); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("description").WhoseValue.Should().Be(todoItem.Description); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); - store.SqlCommands.ShouldHaveCount(1); + store.SqlCommands.Should().HaveCount(1); store.SqlCommands[0].With(command => { @@ -151,7 +151,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", todoItem.Id); }); } @@ -163,9 +163,9 @@ public async Task Can_select_relationship_in_secondary_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); - todoItem.Tags = _fakers.Tag.Generate(1).ToHashSet(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); + todoItem.Tags = _fakers.Tag.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -181,19 +181,19 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("tags"); responseDocument.Data.ManyValue[0].Id.Should().Be(todoItem.Tags.ElementAt(0).StringId); responseDocument.Data.ManyValue[0].Attributes.Should().BeNull(); - responseDocument.Data.ManyValue[0].Relationships.ShouldHaveCount(1); + responseDocument.Data.ManyValue[0].Relationships.Should().HaveCount(1); - responseDocument.Data.ManyValue[0].Relationships.ShouldContainKey("color").With(value => + responseDocument.Data.ManyValue[0].Relationships.Should().ContainKey("color").WhoseValue.With(value => { - value.ShouldNotBeNull(); + value.Should().NotBeNull(); value.Data.Value.Should().BeNull(); }); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -204,7 +204,7 @@ SELECT COUNT(*) WHERE t2."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", todoItem.Id); }); @@ -218,7 +218,7 @@ SELECT COUNT(*) ORDER BY t2."Id" """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", todoItem.Id); }); } @@ -230,7 +230,7 @@ public async Task Can_select_ID() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -246,13 +246,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("people"); responseDocument.Data.SingleValue.Id.Should().Be(person.StringId); responseDocument.Data.SingleValue.Attributes.Should().BeNull(); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); - store.SqlCommands.ShouldHaveCount(1); + store.SqlCommands.Should().HaveCount(1); store.SqlCommands[0].With(command => { @@ -262,7 +262,7 @@ SELECT t1."Id" WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", person.Id); }); } @@ -274,7 +274,7 @@ public async Task Can_select_empty_fieldset() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -290,13 +290,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("people"); responseDocument.Data.SingleValue.Id.Should().Be(person.StringId); responseDocument.Data.SingleValue.Attributes.Should().BeNull(); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); - store.SqlCommands.ShouldHaveCount(1); + store.SqlCommands.Should().HaveCount(1); store.SqlCommands[0].With(command => { @@ -306,7 +306,7 @@ SELECT t1."Id" WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", person.Id); }); } @@ -318,7 +318,7 @@ public async Task Fetches_all_scalar_properties_when_fieldset_contains_readonly_ var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -334,14 +334,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("people"); responseDocument.Data.SingleValue.Id.Should().Be(person.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldHaveCount(1); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("displayName").With(value => value.Should().Be(person.DisplayName)); + responseDocument.Data.SingleValue.Attributes.Should().HaveCount(1); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("displayName").WhoseValue.Should().Be(person.DisplayName); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); - store.SqlCommands.ShouldHaveCount(1); + store.SqlCommands.Should().HaveCount(1); store.SqlCommands[0].With(command => { @@ -351,7 +351,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", person.Id); }); } @@ -363,9 +363,9 @@ public async Task Returns_related_resources_on_broken_resource_linkage() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); - todoItem.Tags = _fakers.Tag.Generate(2).ToHashSet(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); + todoItem.Tags = _fakers.Tag.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -381,17 +381,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("todoItems"); responseDocument.Data.SingleValue.Id.Should().Be(todoItem.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldHaveCount(1); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("description").With(value => value.Should().Be(todoItem.Description)); + responseDocument.Data.SingleValue.Attributes.Should().HaveCount(1); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("description").WhoseValue.Should().Be(todoItem.Description); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); - responseDocument.Included.ShouldHaveCount(2); + responseDocument.Included.Should().HaveCount(2); responseDocument.Included.Should().AllSatisfy(resource => resource.Type.Should().Be("tags")); - store.SqlCommands.ShouldHaveCount(1); + store.SqlCommands.Should().HaveCount(1); store.SqlCommands[0].With(command => { @@ -403,7 +403,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => ORDER BY t2."Id" """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", todoItem.Id); }); } diff --git a/test/DapperTests/IntegrationTests/ReadWrite/Relationships/AddToToManyRelationshipTests.cs b/test/DapperTests/IntegrationTests/ReadWrite/Relationships/AddToToManyRelationshipTests.cs index e6c49c1f62..6f5a87ea33 100644 --- a/test/DapperTests/IntegrationTests/ReadWrite/Relationships/AddToToManyRelationshipTests.cs +++ b/test/DapperTests/IntegrationTests/ReadWrite/Relationships/AddToToManyRelationshipTests.cs @@ -28,11 +28,11 @@ public async Task Can_add_to_OneToMany_relationship() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person existingPerson = _fakers.Person.Generate(); - existingPerson.OwnedTodoItems = _fakers.TodoItem.Generate(1).ToHashSet(); + Person existingPerson = _fakers.Person.GenerateOne(); + existingPerson.OwnedTodoItems = _fakers.TodoItem.GenerateSet(1); - List existingTodoItems = _fakers.TodoItem.Generate(2); - existingTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List existingTodoItems = _fakers.TodoItem.GenerateList(2); + existingTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -73,10 +73,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Person personInDatabase = await dbContext.People.Include(person => person.OwnedTodoItems).FirstWithIdAsync(existingPerson.Id); - personInDatabase.OwnedTodoItems.ShouldHaveCount(3); + personInDatabase.OwnedTodoItems.Should().HaveCount(3); }); - store.SqlCommands.ShouldHaveCount(1); + store.SqlCommands.Should().HaveCount(1); store.SqlCommands[0].With(command => { @@ -86,7 +86,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" IN (@p2, @p3) """)); - command.Parameters.ShouldHaveCount(3); + command.Parameters.Should().HaveCount(3); command.Parameters.Should().Contain("@p1", existingPerson.Id); command.Parameters.Should().Contain("@p2", existingTodoItems.ElementAt(0).Id); command.Parameters.Should().Contain("@p3", existingTodoItems.ElementAt(1).Id); diff --git a/test/DapperTests/IntegrationTests/ReadWrite/Relationships/FetchRelationshipTests.cs b/test/DapperTests/IntegrationTests/ReadWrite/Relationships/FetchRelationshipTests.cs index 227bbdb755..d4703dc99a 100644 --- a/test/DapperTests/IntegrationTests/ReadWrite/Relationships/FetchRelationshipTests.cs +++ b/test/DapperTests/IntegrationTests/ReadWrite/Relationships/FetchRelationshipTests.cs @@ -28,8 +28,8 @@ public async Task Can_get_ToOne_relationship() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -46,13 +46,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("people"); responseDocument.Data.SingleValue.Id.Should().Be(todoItem.Owner.StringId); responseDocument.Meta.Should().BeNull(); - store.SqlCommands.ShouldHaveCount(1); + store.SqlCommands.Should().HaveCount(1); store.SqlCommands[0].With(command => { @@ -63,7 +63,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", todoItem.Id); }); } @@ -75,8 +75,8 @@ public async Task Can_get_empty_ToOne_relationship() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -97,7 +97,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Meta.Should().BeNull(); - store.SqlCommands.ShouldHaveCount(1); + store.SqlCommands.Should().HaveCount(1); store.SqlCommands[0].With(command => { @@ -108,7 +108,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", todoItem.Id); }); } @@ -120,9 +120,9 @@ public async Task Can_get_ToMany_relationship() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); - todoItem.Tags = _fakers.Tag.Generate(2).ToHashSet(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); + todoItem.Tags = _fakers.Tag.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -139,14 +139,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue.Should().AllSatisfy(resource => resource.Type.Should().Be("tags")); responseDocument.Data.ManyValue[0].Id.Should().Be(todoItem.Tags.ElementAt(0).StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(todoItem.Tags.ElementAt(1).StringId); responseDocument.Meta.Should().ContainTotal(2); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -157,7 +157,7 @@ SELECT COUNT(*) WHERE t2."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", todoItem.Id); }); @@ -171,7 +171,7 @@ SELECT COUNT(*) ORDER BY t2."Id" """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", todoItem.Id); }); } @@ -189,7 +189,7 @@ public async Task Cannot_get_relationship_for_unknown_primary_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); diff --git a/test/DapperTests/IntegrationTests/ReadWrite/Relationships/RemoveFromToManyRelationshipTests.cs b/test/DapperTests/IntegrationTests/ReadWrite/Relationships/RemoveFromToManyRelationshipTests.cs index f31a89c73e..ac6be3134e 100644 --- a/test/DapperTests/IntegrationTests/ReadWrite/Relationships/RemoveFromToManyRelationshipTests.cs +++ b/test/DapperTests/IntegrationTests/ReadWrite/Relationships/RemoveFromToManyRelationshipTests.cs @@ -28,9 +28,9 @@ public async Task Can_remove_from_OneToMany_relationship_with_nullable_foreign_k var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person existingPerson = _fakers.Person.Generate(); - existingPerson.AssignedTodoItems = _fakers.TodoItem.Generate(3).ToHashSet(); - existingPerson.AssignedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + Person existingPerson = _fakers.Person.GenerateOne(); + existingPerson.AssignedTodoItems = _fakers.TodoItem.GenerateSet(3); + existingPerson.AssignedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -70,7 +70,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Person personInDatabase = await dbContext.People.Include(person => person.AssignedTodoItems).FirstWithIdAsync(existingPerson.Id); - personInDatabase.AssignedTodoItems.ShouldHaveCount(1); + personInDatabase.AssignedTodoItems.Should().HaveCount(1); personInDatabase.AssignedTodoItems.ElementAt(0).Id.Should().Be(existingPerson.AssignedTodoItems.ElementAt(1).Id); List todoItemInDatabases = await dbContext.TodoItems.Where(todoItem => todoItem.Assignee == null).ToListAsync(); @@ -78,7 +78,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => todoItemInDatabases.Should().HaveCount(2); }); - store.SqlCommands.ShouldHaveCount(3); + store.SqlCommands.Should().HaveCount(3); store.SqlCommands[0].With(command => { @@ -93,7 +93,7 @@ LEFT JOIN ( WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(3); + command.Parameters.Should().HaveCount(3); command.Parameters.Should().Contain("@p1", existingPerson.Id); command.Parameters.Should().Contain("@p2", existingPerson.AssignedTodoItems.ElementAt(0).Id); command.Parameters.Should().Contain("@p3", existingPerson.AssignedTodoItems.ElementAt(2).Id); @@ -107,7 +107,7 @@ SELECT t1."Id" WHERE t1."Id" IN (@p1, @p2) """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", existingPerson.AssignedTodoItems.ElementAt(0).Id); command.Parameters.Should().Contain("@p2", existingPerson.AssignedTodoItems.ElementAt(2).Id); }); @@ -120,7 +120,7 @@ SELECT t1."Id" WHERE "Id" IN (@p2, @p3) """)); - command.Parameters.ShouldHaveCount(3); + command.Parameters.Should().HaveCount(3); command.Parameters.Should().Contain("@p1", null); command.Parameters.Should().Contain("@p2", existingPerson.AssignedTodoItems.ElementAt(0).Id); command.Parameters.Should().Contain("@p3", existingPerson.AssignedTodoItems.ElementAt(2).Id); @@ -134,8 +134,8 @@ public async Task Can_remove_from_OneToMany_relationship_with_required_foreign_k var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person existingPerson = _fakers.Person.Generate(); - existingPerson.OwnedTodoItems = _fakers.TodoItem.Generate(3).ToHashSet(); + Person existingPerson = _fakers.Person.GenerateOne(); + existingPerson.OwnedTodoItems = _fakers.TodoItem.GenerateSet(3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -175,7 +175,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Person personInDatabase = await dbContext.People.Include(person => person.OwnedTodoItems).FirstWithIdAsync(existingPerson.Id); - personInDatabase.OwnedTodoItems.ShouldHaveCount(1); + personInDatabase.OwnedTodoItems.Should().HaveCount(1); personInDatabase.OwnedTodoItems.ElementAt(0).Id.Should().Be(existingPerson.OwnedTodoItems.ElementAt(1).Id); List todoItemInDatabases = await dbContext.TodoItems.ToListAsync(); @@ -183,7 +183,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => todoItemInDatabases.Should().HaveCount(1); }); - store.SqlCommands.ShouldHaveCount(3); + store.SqlCommands.Should().HaveCount(3); store.SqlCommands[0].With(command => { @@ -198,7 +198,7 @@ LEFT JOIN ( WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(3); + command.Parameters.Should().HaveCount(3); command.Parameters.Should().Contain("@p1", existingPerson.Id); command.Parameters.Should().Contain("@p2", existingPerson.OwnedTodoItems.ElementAt(0).Id); command.Parameters.Should().Contain("@p3", existingPerson.OwnedTodoItems.ElementAt(2).Id); @@ -212,7 +212,7 @@ SELECT t1."Id" WHERE t1."Id" IN (@p1, @p2) """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", existingPerson.OwnedTodoItems.ElementAt(0).Id); command.Parameters.Should().Contain("@p2", existingPerson.OwnedTodoItems.ElementAt(2).Id); }); @@ -224,7 +224,7 @@ DELETE FROM "TodoItems" WHERE "Id" IN (@p1, @p2) """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", existingPerson.OwnedTodoItems.ElementAt(0).Id); command.Parameters.Should().Contain("@p2", existingPerson.OwnedTodoItems.ElementAt(2).Id); }); diff --git a/test/DapperTests/IntegrationTests/ReadWrite/Relationships/ReplaceToManyRelationshipTests.cs b/test/DapperTests/IntegrationTests/ReadWrite/Relationships/ReplaceToManyRelationshipTests.cs index 05b0710132..a46a34678b 100644 --- a/test/DapperTests/IntegrationTests/ReadWrite/Relationships/ReplaceToManyRelationshipTests.cs +++ b/test/DapperTests/IntegrationTests/ReadWrite/Relationships/ReplaceToManyRelationshipTests.cs @@ -27,9 +27,9 @@ public async Task Can_clear_OneToMany_relationship_with_nullable_foreign_key() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person existingPerson = _fakers.Person.Generate(); - existingPerson.AssignedTodoItems = _fakers.TodoItem.Generate(2).ToHashSet(); - existingPerson.AssignedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + Person existingPerson = _fakers.Person.GenerateOne(); + existingPerson.AssignedTodoItems = _fakers.TodoItem.GenerateSet(2); + existingPerson.AssignedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -59,7 +59,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => personInDatabase.AssignedTodoItems.Should().BeEmpty(); }); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -70,7 +70,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingPerson.Id); }); @@ -82,7 +82,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" IN (@p2, @p3) """)); - command.Parameters.ShouldHaveCount(3); + command.Parameters.Should().HaveCount(3); command.Parameters.Should().Contain("@p1", null); command.Parameters.Should().Contain("@p2", existingPerson.AssignedTodoItems.ElementAt(0).Id); command.Parameters.Should().Contain("@p3", existingPerson.AssignedTodoItems.ElementAt(1).Id); @@ -95,9 +95,9 @@ public async Task Can_clear_OneToMany_relationship_with_required_foreign_key() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person existingPerson = _fakers.Person.Generate(); - existingPerson.OwnedTodoItems = _fakers.TodoItem.Generate(2).ToHashSet(); - existingPerson.OwnedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + Person existingPerson = _fakers.Person.GenerateOne(); + existingPerson.OwnedTodoItems = _fakers.TodoItem.GenerateSet(2); + existingPerson.OwnedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -127,7 +127,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => personInDatabase.OwnedTodoItems.Should().BeEmpty(); }); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -138,7 +138,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingPerson.Id); }); @@ -149,7 +149,7 @@ DELETE FROM "TodoItems" WHERE "Id" IN (@p1, @p2) """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", existingPerson.OwnedTodoItems.ElementAt(0).Id); command.Parameters.Should().Contain("@p2", existingPerson.OwnedTodoItems.ElementAt(1).Id); }); @@ -161,10 +161,10 @@ public async Task Can_create_OneToMany_relationship() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person existingPerson = _fakers.Person.Generate(); + Person existingPerson = _fakers.Person.GenerateOne(); - List existingTodoItems = _fakers.TodoItem.Generate(2); - existingTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List existingTodoItems = _fakers.TodoItem.GenerateList(2); + existingTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -204,12 +204,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Person personInDatabase = await dbContext.People.Include(person => person.AssignedTodoItems).FirstWithIdAsync(existingPerson.Id); - personInDatabase.AssignedTodoItems.ShouldHaveCount(2); + personInDatabase.AssignedTodoItems.Should().HaveCount(2); personInDatabase.AssignedTodoItems.ElementAt(0).Id.Should().Be(existingTodoItems.ElementAt(0).Id); personInDatabase.AssignedTodoItems.ElementAt(1).Id.Should().Be(existingTodoItems.ElementAt(1).Id); }); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -220,7 +220,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingPerson.Id); }); @@ -232,7 +232,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" IN (@p2, @p3) """)); - command.Parameters.ShouldHaveCount(3); + command.Parameters.Should().HaveCount(3); command.Parameters.Should().Contain("@p1", existingPerson.Id); command.Parameters.Should().Contain("@p2", existingTodoItems.ElementAt(0).Id); command.Parameters.Should().Contain("@p3", existingTodoItems.ElementAt(1).Id); @@ -245,12 +245,12 @@ public async Task Can_replace_OneToMany_relationship_with_nullable_foreign_key() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person existingPerson = _fakers.Person.Generate(); - existingPerson.AssignedTodoItems = _fakers.TodoItem.Generate(1).ToHashSet(); - existingPerson.AssignedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + Person existingPerson = _fakers.Person.GenerateOne(); + existingPerson.AssignedTodoItems = _fakers.TodoItem.GenerateSet(1); + existingPerson.AssignedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); - TodoItem existingTodoItem = _fakers.TodoItem.Generate(); - existingTodoItem.Owner = _fakers.Person.Generate(); + TodoItem existingTodoItem = _fakers.TodoItem.GenerateOne(); + existingTodoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -284,11 +284,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Person personInDatabase = await dbContext.People.Include(person => person.AssignedTodoItems).FirstWithIdAsync(existingPerson.Id); - personInDatabase.AssignedTodoItems.ShouldHaveCount(1); + personInDatabase.AssignedTodoItems.Should().HaveCount(1); personInDatabase.AssignedTodoItems.ElementAt(0).Id.Should().Be(existingTodoItem.Id); }); - store.SqlCommands.ShouldHaveCount(3); + store.SqlCommands.Should().HaveCount(3); store.SqlCommands[0].With(command => { @@ -299,7 +299,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingPerson.Id); }); @@ -311,7 +311,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", null); command.Parameters.Should().Contain("@p2", existingPerson.AssignedTodoItems.ElementAt(0).Id); }); @@ -324,7 +324,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", existingPerson.Id); command.Parameters.Should().Contain("@p2", existingTodoItem.Id); }); @@ -336,12 +336,12 @@ public async Task Can_replace_OneToMany_relationship_with_required_foreign_key() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person existingPerson = _fakers.Person.Generate(); - existingPerson.OwnedTodoItems = _fakers.TodoItem.Generate(1).ToHashSet(); - existingPerson.OwnedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + Person existingPerson = _fakers.Person.GenerateOne(); + existingPerson.OwnedTodoItems = _fakers.TodoItem.GenerateSet(1); + existingPerson.OwnedTodoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); - TodoItem existingTodoItem = _fakers.TodoItem.Generate(); - existingTodoItem.Owner = _fakers.Person.Generate(); + TodoItem existingTodoItem = _fakers.TodoItem.GenerateOne(); + existingTodoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -375,11 +375,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Person personInDatabase = await dbContext.People.Include(person => person.OwnedTodoItems).FirstWithIdAsync(existingPerson.Id); - personInDatabase.OwnedTodoItems.ShouldHaveCount(1); + personInDatabase.OwnedTodoItems.Should().HaveCount(1); personInDatabase.OwnedTodoItems.ElementAt(0).Id.Should().Be(existingTodoItem.Id); }); - store.SqlCommands.ShouldHaveCount(3); + store.SqlCommands.Should().HaveCount(3); store.SqlCommands[0].With(command => { @@ -390,7 +390,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingPerson.Id); }); @@ -401,7 +401,7 @@ DELETE FROM "TodoItems" WHERE "Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingPerson.OwnedTodoItems.ElementAt(0).Id); }); @@ -413,7 +413,7 @@ DELETE FROM "TodoItems" WHERE "Id" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", existingPerson.Id); command.Parameters.Should().Contain("@p2", existingTodoItem.Id); }); diff --git a/test/DapperTests/IntegrationTests/ReadWrite/Relationships/UpdateToOneRelationshipTests.cs b/test/DapperTests/IntegrationTests/ReadWrite/Relationships/UpdateToOneRelationshipTests.cs index e42efaf2e1..bab60bf29b 100644 --- a/test/DapperTests/IntegrationTests/ReadWrite/Relationships/UpdateToOneRelationshipTests.cs +++ b/test/DapperTests/IntegrationTests/ReadWrite/Relationships/UpdateToOneRelationshipTests.cs @@ -28,9 +28,9 @@ public async Task Can_clear_OneToOne_relationship_with_nullable_foreign_key_at_l var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person existingPerson = _fakers.Person.Generate(); - existingPerson.Account = _fakers.LoginAccount.Generate(); - existingPerson.Account.Recovery = _fakers.AccountRecovery.Generate(); + Person existingPerson = _fakers.Person.GenerateOne(); + existingPerson.Account = _fakers.LoginAccount.GenerateOne(); + existingPerson.Account.Recovery = _fakers.AccountRecovery.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -65,7 +65,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => loginAccountInDatabase.Person.Should().BeNull(); }); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -76,7 +76,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingPerson.Id); }); @@ -88,7 +88,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", null); command.Parameters.Should().Contain("@p2", existingPerson.Id); }); @@ -100,9 +100,9 @@ public async Task Can_clear_OneToOne_relationship_with_nullable_foreign_key_at_r var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - LoginAccount existingLoginAccount = _fakers.LoginAccount.Generate(); - existingLoginAccount.Recovery = _fakers.AccountRecovery.Generate(); - existingLoginAccount.Person = _fakers.Person.Generate(); + LoginAccount existingLoginAccount = _fakers.LoginAccount.GenerateOne(); + existingLoginAccount.Recovery = _fakers.AccountRecovery.GenerateOne(); + existingLoginAccount.Person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -137,7 +137,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => personInDatabase.Account.Should().BeNull(); }); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -148,7 +148,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingLoginAccount.Id); }); @@ -160,7 +160,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", null); command.Parameters.Should().Contain("@p2", existingLoginAccount.Person.Id); }); @@ -172,8 +172,8 @@ public async Task Can_clear_OneToOne_relationship_with_nullable_foreign_key_at_r var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - LoginAccount existingLoginAccount = _fakers.LoginAccount.Generate(); - existingLoginAccount.Recovery = _fakers.AccountRecovery.Generate(); + LoginAccount existingLoginAccount = _fakers.LoginAccount.GenerateOne(); + existingLoginAccount.Recovery = _fakers.AccountRecovery.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -196,7 +196,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Should().BeEmpty(); - store.SqlCommands.ShouldHaveCount(1); + store.SqlCommands.Should().HaveCount(1); store.SqlCommands[0].With(command => { @@ -207,7 +207,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingLoginAccount.Id); }); } @@ -218,8 +218,8 @@ public async Task Cannot_clear_OneToOne_relationship_with_required_foreign_key_a var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - LoginAccount existingLoginAccount = _fakers.LoginAccount.Generate(); - existingLoginAccount.Recovery = _fakers.AccountRecovery.Generate(); + LoginAccount existingLoginAccount = _fakers.LoginAccount.GenerateOne(); + existingLoginAccount.Recovery = _fakers.AccountRecovery.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -240,7 +240,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); @@ -248,7 +248,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => error.Detail.Should().Be("The relationship 'recovery' on resource type 'loginAccounts' cannot be cleared because it is a required relationship."); error.Source.Should().BeNull(); - store.SqlCommands.ShouldHaveCount(1); + store.SqlCommands.Should().HaveCount(1); store.SqlCommands[0].With(command => { @@ -259,7 +259,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingLoginAccount.Id); }); } @@ -270,8 +270,8 @@ public async Task Cannot_clear_OneToOne_relationship_with_required_foreign_key_a var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - AccountRecovery existingAccountRecovery = _fakers.AccountRecovery.Generate(); - existingAccountRecovery.Account = _fakers.LoginAccount.Generate(); + AccountRecovery existingAccountRecovery = _fakers.AccountRecovery.GenerateOne(); + existingAccountRecovery.Account = _fakers.LoginAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -292,7 +292,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); @@ -300,7 +300,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => error.Detail.Should().Be("The relationship 'account' on resource type 'accountRecoveries' cannot be cleared because it is a required relationship."); error.Source.Should().BeNull(); - store.SqlCommands.ShouldHaveCount(1); + store.SqlCommands.Should().HaveCount(1); store.SqlCommands[0].With(command => { @@ -311,7 +311,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingAccountRecovery.Id); }); } @@ -322,9 +322,9 @@ public async Task Can_clear_ManyToOne_relationship_with_nullable_foreign_key() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem existingTodoItem = _fakers.TodoItem.Generate(); - existingTodoItem.Owner = _fakers.Person.Generate(); - existingTodoItem.Assignee = _fakers.Person.Generate(); + TodoItem existingTodoItem = _fakers.TodoItem.GenerateOne(); + existingTodoItem.Owner = _fakers.Person.GenerateOne(); + existingTodoItem.Assignee = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -354,7 +354,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => todoItemInDatabase.Assignee.Should().BeNull(); }); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -365,7 +365,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingTodoItem.Id); }); @@ -377,7 +377,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", null); command.Parameters.Should().Contain("@p2", existingTodoItem.Id); }); @@ -389,8 +389,8 @@ public async Task Cannot_clear_ManyToOne_relationship_with_required_foreign_key( var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem existingTodoItem = _fakers.TodoItem.Generate(); - existingTodoItem.Owner = _fakers.Person.Generate(); + TodoItem existingTodoItem = _fakers.TodoItem.GenerateOne(); + existingTodoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -411,7 +411,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); @@ -419,7 +419,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => error.Detail.Should().Be("The relationship 'owner' on resource type 'todoItems' cannot be cleared because it is a required relationship."); error.Source.Should().BeNull(); - store.SqlCommands.ShouldHaveCount(1); + store.SqlCommands.Should().HaveCount(1); store.SqlCommands[0].With(command => { @@ -430,7 +430,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingTodoItem.Id); }); } @@ -441,10 +441,10 @@ public async Task Can_create_OneToOne_relationship_with_nullable_foreign_key_at_ var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person existingPerson = _fakers.Person.Generate(); + Person existingPerson = _fakers.Person.GenerateOne(); - LoginAccount existingLoginAccount = _fakers.LoginAccount.Generate(); - existingLoginAccount.Recovery = _fakers.AccountRecovery.Generate(); + LoginAccount existingLoginAccount = _fakers.LoginAccount.GenerateOne(); + existingLoginAccount.Recovery = _fakers.AccountRecovery.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -475,11 +475,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Person personInDatabase = await dbContext.People.Include(person => person.Account).FirstWithIdAsync(existingPerson.Id); - personInDatabase.Account.ShouldNotBeNull(); + personInDatabase.Account.Should().NotBeNull(); personInDatabase.Account.Id.Should().Be(existingLoginAccount.Id); }); - store.SqlCommands.ShouldHaveCount(3); + store.SqlCommands.Should().HaveCount(3); store.SqlCommands[0].With(command => { @@ -490,7 +490,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingPerson.Id); }); @@ -502,7 +502,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "AccountId" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", null); command.Parameters.Should().Contain("@p2", existingLoginAccount.Id); }); @@ -515,7 +515,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", existingLoginAccount.Id); command.Parameters.Should().Contain("@p2", existingPerson.Id); }); @@ -527,10 +527,10 @@ public async Task Can_create_OneToOne_relationship_with_nullable_foreign_key_at_ var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - LoginAccount existingLoginAccount = _fakers.LoginAccount.Generate(); - existingLoginAccount.Recovery = _fakers.AccountRecovery.Generate(); + LoginAccount existingLoginAccount = _fakers.LoginAccount.GenerateOne(); + existingLoginAccount.Recovery = _fakers.AccountRecovery.GenerateOne(); - Person existingPerson = _fakers.Person.Generate(); + Person existingPerson = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -562,11 +562,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => LoginAccount loginAccountInDatabase = await dbContext.LoginAccounts.Include(loginAccount => loginAccount.Person).FirstWithIdAsync(existingLoginAccount.Id); - loginAccountInDatabase.Person.ShouldNotBeNull(); + loginAccountInDatabase.Person.Should().NotBeNull(); loginAccountInDatabase.Person.Id.Should().Be(existingPerson.Id); }); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -577,7 +577,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingLoginAccount.Id); }); @@ -589,7 +589,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", existingLoginAccount.Id); command.Parameters.Should().Contain("@p2", existingPerson.Id); }); @@ -601,10 +601,10 @@ public async Task Can_create_ManyToOne_relationship_with_nullable_foreign_key() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem existingTodoItem = _fakers.TodoItem.Generate(); - existingTodoItem.Owner = _fakers.Person.Generate(); + TodoItem existingTodoItem = _fakers.TodoItem.GenerateOne(); + existingTodoItem.Owner = _fakers.Person.GenerateOne(); - Person existingPerson = _fakers.Person.Generate(); + Person existingPerson = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -635,11 +635,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { TodoItem todoItemInDatabase = await dbContext.TodoItems.Include(todoItem => todoItem.Assignee).FirstWithIdAsync(existingTodoItem.Id); - todoItemInDatabase.Assignee.ShouldNotBeNull(); + todoItemInDatabase.Assignee.Should().NotBeNull(); todoItemInDatabase.Assignee.Id.Should().Be(existingPerson.Id); }); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -650,7 +650,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingTodoItem.Id); }); @@ -662,7 +662,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", existingPerson.Id); command.Parameters.Should().Contain("@p2", existingTodoItem.Id); }); @@ -674,13 +674,13 @@ public async Task Can_replace_OneToOne_relationship_with_nullable_foreign_key_at var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person existingPerson1 = _fakers.Person.Generate(); - existingPerson1.Account = _fakers.LoginAccount.Generate(); - existingPerson1.Account.Recovery = _fakers.AccountRecovery.Generate(); + Person existingPerson1 = _fakers.Person.GenerateOne(); + existingPerson1.Account = _fakers.LoginAccount.GenerateOne(); + existingPerson1.Account.Recovery = _fakers.AccountRecovery.GenerateOne(); - Person existingPerson2 = _fakers.Person.Generate(); - existingPerson2.Account = _fakers.LoginAccount.Generate(); - existingPerson2.Account.Recovery = _fakers.AccountRecovery.Generate(); + Person existingPerson2 = _fakers.Person.GenerateOne(); + existingPerson2.Account = _fakers.LoginAccount.GenerateOne(); + existingPerson2.Account.Recovery = _fakers.AccountRecovery.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -711,7 +711,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Person personInDatabase1 = await dbContext.People.Include(person => person.Account).FirstWithIdAsync(existingPerson1.Id); - personInDatabase1.Account.ShouldNotBeNull(); + personInDatabase1.Account.Should().NotBeNull(); personInDatabase1.Account.Id.Should().Be(existingPerson2.Account.Id); Person personInDatabase2 = await dbContext.People.Include(person => person.Account).FirstWithIdAsync(existingPerson2.Id); @@ -719,7 +719,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => personInDatabase2.Account.Should().BeNull(); }); - store.SqlCommands.ShouldHaveCount(3); + store.SqlCommands.Should().HaveCount(3); store.SqlCommands[0].With(command => { @@ -730,7 +730,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingPerson1.Id); }); @@ -742,7 +742,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "AccountId" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", null); command.Parameters.Should().Contain("@p2", existingPerson2.Account.Id); }); @@ -755,7 +755,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", existingPerson2.Account.Id); command.Parameters.Should().Contain("@p2", existingPerson1.Id); }); @@ -767,13 +767,13 @@ public async Task Can_replace_OneToOne_relationship_with_nullable_foreign_key_at var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - LoginAccount existingLoginAccount1 = _fakers.LoginAccount.Generate(); - existingLoginAccount1.Recovery = _fakers.AccountRecovery.Generate(); - existingLoginAccount1.Person = _fakers.Person.Generate(); + LoginAccount existingLoginAccount1 = _fakers.LoginAccount.GenerateOne(); + existingLoginAccount1.Recovery = _fakers.AccountRecovery.GenerateOne(); + existingLoginAccount1.Person = _fakers.Person.GenerateOne(); - LoginAccount existingLoginAccount2 = _fakers.LoginAccount.Generate(); - existingLoginAccount2.Recovery = _fakers.AccountRecovery.Generate(); - existingLoginAccount2.Person = _fakers.Person.Generate(); + LoginAccount existingLoginAccount2 = _fakers.LoginAccount.GenerateOne(); + existingLoginAccount2.Recovery = _fakers.AccountRecovery.GenerateOne(); + existingLoginAccount2.Person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -805,7 +805,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => LoginAccount loginAccountInDatabase1 = await dbContext.LoginAccounts.Include(loginAccount => loginAccount.Person).FirstWithIdAsync(existingLoginAccount1.Id); - loginAccountInDatabase1.Person.ShouldNotBeNull(); + loginAccountInDatabase1.Person.Should().NotBeNull(); loginAccountInDatabase1.Person.Id.Should().Be(existingLoginAccount2.Person.Id); LoginAccount loginAccountInDatabase2 = @@ -814,7 +814,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => loginAccountInDatabase2.Person.Should().BeNull(); }); - store.SqlCommands.ShouldHaveCount(3); + store.SqlCommands.Should().HaveCount(3); store.SqlCommands[0].With(command => { @@ -825,7 +825,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingLoginAccount1.Id); }); @@ -837,7 +837,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", null); command.Parameters.Should().Contain("@p2", existingLoginAccount1.Person.Id); }); @@ -850,7 +850,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", existingLoginAccount1.Id); command.Parameters.Should().Contain("@p2", existingLoginAccount2.Person.Id); }); @@ -862,11 +862,11 @@ public async Task Can_replace_OneToOne_relationship_with_required_foreign_key_at var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - LoginAccount existingLoginAccount1 = _fakers.LoginAccount.Generate(); - existingLoginAccount1.Recovery = _fakers.AccountRecovery.Generate(); + LoginAccount existingLoginAccount1 = _fakers.LoginAccount.GenerateOne(); + existingLoginAccount1.Recovery = _fakers.AccountRecovery.GenerateOne(); - LoginAccount existingLoginAccount2 = _fakers.LoginAccount.Generate(); - existingLoginAccount2.Recovery = _fakers.AccountRecovery.Generate(); + LoginAccount existingLoginAccount2 = _fakers.LoginAccount.GenerateOne(); + existingLoginAccount2.Recovery = _fakers.AccountRecovery.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -898,7 +898,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => LoginAccount loginAccountInDatabase1 = await dbContext.LoginAccounts.Include(loginAccount => loginAccount.Recovery).FirstWithIdAsync(existingLoginAccount1.Id); - loginAccountInDatabase1.Recovery.ShouldNotBeNull(); + loginAccountInDatabase1.Recovery.Should().NotBeNull(); loginAccountInDatabase1.Recovery.Id.Should().Be(existingLoginAccount2.Recovery.Id); LoginAccount? loginAccountInDatabase2 = await dbContext.LoginAccounts.Include(loginAccount => loginAccount.Recovery) @@ -907,7 +907,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => loginAccountInDatabase2.Should().BeNull(); }); - store.SqlCommands.ShouldHaveCount(3); + store.SqlCommands.Should().HaveCount(3); store.SqlCommands[0].With(command => { @@ -918,7 +918,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingLoginAccount1.Id); }); @@ -929,7 +929,7 @@ DELETE FROM "LoginAccounts" WHERE "RecoveryId" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingLoginAccount2.Recovery.Id); }); @@ -941,7 +941,7 @@ DELETE FROM "LoginAccounts" WHERE "Id" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", existingLoginAccount2.Recovery.Id); command.Parameters.Should().Contain("@p2", existingLoginAccount1.Id); }); @@ -953,11 +953,11 @@ public async Task Can_replace_OneToOne_relationship_with_required_foreign_key_at var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - AccountRecovery existingAccountRecovery1 = _fakers.AccountRecovery.Generate(); - existingAccountRecovery1.Account = _fakers.LoginAccount.Generate(); + AccountRecovery existingAccountRecovery1 = _fakers.AccountRecovery.GenerateOne(); + existingAccountRecovery1.Account = _fakers.LoginAccount.GenerateOne(); - AccountRecovery existingAccountRecovery2 = _fakers.AccountRecovery.Generate(); - existingAccountRecovery2.Account = _fakers.LoginAccount.Generate(); + AccountRecovery existingAccountRecovery2 = _fakers.AccountRecovery.GenerateOne(); + existingAccountRecovery2.Account = _fakers.LoginAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -989,7 +989,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => AccountRecovery accountRecoveryInDatabase1 = await dbContext.AccountRecoveries.Include(recovery => recovery.Account).FirstWithIdAsync(existingAccountRecovery1.Id); - accountRecoveryInDatabase1.Account.ShouldNotBeNull(); + accountRecoveryInDatabase1.Account.Should().NotBeNull(); accountRecoveryInDatabase1.Account.Id.Should().Be(existingAccountRecovery2.Account.Id); AccountRecovery accountRecoveryInDatabase2 = @@ -998,7 +998,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => accountRecoveryInDatabase2.Account.Should().BeNull(); }); - store.SqlCommands.ShouldHaveCount(3); + store.SqlCommands.Should().HaveCount(3); store.SqlCommands[0].With(command => { @@ -1009,7 +1009,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingAccountRecovery1.Id); }); @@ -1020,7 +1020,7 @@ DELETE FROM "LoginAccounts" WHERE "Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingAccountRecovery1.Account.Id); }); @@ -1032,7 +1032,7 @@ DELETE FROM "LoginAccounts" WHERE "Id" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", existingAccountRecovery1.Id); command.Parameters.Should().Contain("@p2", existingAccountRecovery2.Account.Id); }); @@ -1044,13 +1044,13 @@ public async Task Can_replace_ManyToOne_relationship_with_nullable_foreign_key() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem existingTodoItem1 = _fakers.TodoItem.Generate(); - existingTodoItem1.Owner = _fakers.Person.Generate(); - existingTodoItem1.Assignee = _fakers.Person.Generate(); + TodoItem existingTodoItem1 = _fakers.TodoItem.GenerateOne(); + existingTodoItem1.Owner = _fakers.Person.GenerateOne(); + existingTodoItem1.Assignee = _fakers.Person.GenerateOne(); - TodoItem existingTodoItem2 = _fakers.TodoItem.Generate(); - existingTodoItem2.Owner = _fakers.Person.Generate(); - existingTodoItem2.Assignee = _fakers.Person.Generate(); + TodoItem existingTodoItem2 = _fakers.TodoItem.GenerateOne(); + existingTodoItem2.Owner = _fakers.Person.GenerateOne(); + existingTodoItem2.Assignee = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1081,11 +1081,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { TodoItem todoItemInDatabase1 = await dbContext.TodoItems.Include(todoItem => todoItem.Assignee).FirstWithIdAsync(existingTodoItem1.Id); - todoItemInDatabase1.Assignee.ShouldNotBeNull(); + todoItemInDatabase1.Assignee.Should().NotBeNull(); todoItemInDatabase1.Assignee.Id.Should().Be(existingTodoItem2.Assignee.Id); }); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -1096,7 +1096,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingTodoItem1.Id); }); @@ -1108,7 +1108,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", existingTodoItem2.Assignee.Id); command.Parameters.Should().Contain("@p2", existingTodoItem1.Id); }); @@ -1120,11 +1120,11 @@ public async Task Can_replace_ManyToOne_relationship_with_required_foreign_key() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem existingTodoItem1 = _fakers.TodoItem.Generate(); - existingTodoItem1.Owner = _fakers.Person.Generate(); + TodoItem existingTodoItem1 = _fakers.TodoItem.GenerateOne(); + existingTodoItem1.Owner = _fakers.Person.GenerateOne(); - TodoItem existingTodoItem2 = _fakers.TodoItem.Generate(); - existingTodoItem2.Owner = _fakers.Person.Generate(); + TodoItem existingTodoItem2 = _fakers.TodoItem.GenerateOne(); + existingTodoItem2.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1155,11 +1155,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { TodoItem todoItemInDatabase1 = await dbContext.TodoItems.Include(todoItem => todoItem.Owner).FirstWithIdAsync(existingTodoItem1.Id); - todoItemInDatabase1.Owner.ShouldNotBeNull(); + todoItemInDatabase1.Owner.Should().NotBeNull(); todoItemInDatabase1.Owner.Id.Should().Be(existingTodoItem2.Owner.Id); }); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -1170,7 +1170,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingTodoItem1.Id); }); @@ -1182,7 +1182,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", existingTodoItem2.Owner.Id); command.Parameters.Should().Contain("@p2", existingTodoItem1.Id); }); diff --git a/test/DapperTests/IntegrationTests/ReadWrite/Resources/CreateResourceTests.cs b/test/DapperTests/IntegrationTests/ReadWrite/Resources/CreateResourceTests.cs index 199c8641e6..ce74e99839 100644 --- a/test/DapperTests/IntegrationTests/ReadWrite/Resources/CreateResourceTests.cs +++ b/test/DapperTests/IntegrationTests/ReadWrite/Resources/CreateResourceTests.cs @@ -29,10 +29,10 @@ public async Task Can_create_resource() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem newTodoItem = _fakers.TodoItem.Generate(); + TodoItem newTodoItem = _fakers.TodoItem.GenerateOne(); - Person existingPerson = _fakers.Person.Generate(); - Tag existingTag = _fakers.Tag.Generate(); + Person existingPerson = _fakers.Person.GenerateOne(); + Tag existingTag = _fakers.Tag.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -92,17 +92,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("todoItems"); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("description").With(value => value.Should().Be(newTodoItem.Description)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("priority").With(value => value.Should().Be(newTodoItem.Priority)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("durationInHours").With(value => value.Should().Be(newTodoItem.DurationInHours)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("createdAt").With(value => value.Should().Be(DapperTestContext.FrozenTime)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("modifiedAt").With(value => value.Should().BeNull()); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("description").WhoseValue.Should().Be(newTodoItem.Description); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("priority").WhoseValue.Should().Be(newTodoItem.Priority); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("durationInHours").WhoseValue.Should().Be(newTodoItem.DurationInHours); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("createdAt").WhoseValue.Should().Be(DapperTestContext.FrozenTime); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("modifiedAt").WhoseValue.Should().BeNull(); - responseDocument.Data.SingleValue.Relationships.ShouldOnlyContainKeys("owner", "assignee", "tags"); + responseDocument.Data.SingleValue.Relationships.Should().OnlyContainKeys("owner", "assignee", "tags"); - long newTodoItemId = long.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + long newTodoItemId = long.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); httpResponse.Headers.Location.Should().Be($"/todoItems/{newTodoItemId}"); await _testContext.RunOnDatabaseAsync(async dbContext => @@ -125,15 +125,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => todoItemInDatabase.CreatedAt.Should().Be(DapperTestContext.FrozenTime); todoItemInDatabase.LastModifiedAt.Should().BeNull(); - todoItemInDatabase.Owner.ShouldNotBeNull(); + todoItemInDatabase.Owner.Should().NotBeNull(); todoItemInDatabase.Owner.Id.Should().Be(existingPerson.Id); - todoItemInDatabase.Assignee.ShouldNotBeNull(); + todoItemInDatabase.Assignee.Should().NotBeNull(); todoItemInDatabase.Assignee.Id.Should().Be(existingPerson.Id); - todoItemInDatabase.Tags.ShouldHaveCount(1); + todoItemInDatabase.Tags.Should().HaveCount(1); todoItemInDatabase.Tags.ElementAt(0).Id.Should().Be(existingTag.Id); }); - store.SqlCommands.ShouldHaveCount(3); + store.SqlCommands.Should().HaveCount(3); store.SqlCommands[0].With(command => { @@ -143,7 +143,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => RETURNING "Id" """)); - command.Parameters.ShouldHaveCount(7); + command.Parameters.Should().HaveCount(7); command.Parameters.Should().Contain("@p1", newTodoItem.Description); command.Parameters.Should().Contain("@p2", newTodoItem.Priority); command.Parameters.Should().Contain("@p3", newTodoItem.DurationInHours); @@ -161,7 +161,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", newTodoItemId); command.Parameters.Should().Contain("@p2", existingTag.Id); }); @@ -174,7 +174,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", newTodoItemId); }); } @@ -186,9 +186,9 @@ public async Task Can_create_resource_with_only_required_fields() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem newTodoItem = _fakers.TodoItem.Generate(); + TodoItem newTodoItem = _fakers.TodoItem.GenerateOne(); - Person existingPerson = _fakers.Person.Generate(); + Person existingPerson = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -228,16 +228,16 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("todoItems"); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("description").With(value => value.Should().Be(newTodoItem.Description)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("priority").With(value => value.Should().Be(newTodoItem.Priority)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("durationInHours").With(value => value.Should().BeNull()); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("createdAt").With(value => value.Should().Be(DapperTestContext.FrozenTime)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("modifiedAt").With(value => value.Should().BeNull()); - responseDocument.Data.SingleValue.Relationships.ShouldOnlyContainKeys("owner", "assignee", "tags"); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("description").WhoseValue.Should().Be(newTodoItem.Description); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("priority").WhoseValue.Should().Be(newTodoItem.Priority); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("durationInHours").WhoseValue.Should().BeNull(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("createdAt").WhoseValue.Should().Be(DapperTestContext.FrozenTime); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("modifiedAt").WhoseValue.Should().BeNull(); + responseDocument.Data.SingleValue.Relationships.Should().OnlyContainKeys("owner", "assignee", "tags"); - long newTodoItemId = long.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + long newTodoItemId = long.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -259,13 +259,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => todoItemInDatabase.CreatedAt.Should().Be(DapperTestContext.FrozenTime); todoItemInDatabase.LastModifiedAt.Should().BeNull(); - todoItemInDatabase.Owner.ShouldNotBeNull(); + todoItemInDatabase.Owner.Should().NotBeNull(); todoItemInDatabase.Owner.Id.Should().Be(existingPerson.Id); todoItemInDatabase.Assignee.Should().BeNull(); todoItemInDatabase.Tags.Should().BeEmpty(); }); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -275,7 +275,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => RETURNING "Id" """)); - command.Parameters.ShouldHaveCount(7); + command.Parameters.Should().HaveCount(7); command.Parameters.Should().Contain("@p1", newTodoItem.Description); command.Parameters.Should().Contain("@p2", newTodoItem.Priority); command.Parameters.Should().Contain("@p3", null); @@ -293,7 +293,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", newTodoItemId); }); } @@ -324,27 +324,27 @@ public async Task Cannot_create_resource_without_required_fields() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(3); + responseDocument.Errors.Should().HaveCount(3); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error1.Title.Should().Be("Input validation failed."); error1.Detail.Should().Be("The Owner field is required."); - error1.Source.ShouldNotBeNull(); + error1.Source.Should().NotBeNull(); error1.Source.Pointer.Should().Be("/data/relationships/owner/data"); ErrorObject error2 = responseDocument.Errors[1]; error2.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error2.Title.Should().Be("Input validation failed."); error2.Detail.Should().Be("The Priority field is required."); - error2.Source.ShouldNotBeNull(); + error2.Source.Should().NotBeNull(); error2.Source.Pointer.Should().Be("/data/attributes/priority"); ErrorObject error3 = responseDocument.Errors[2]; error3.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error3.Title.Should().Be("Input validation failed."); error3.Detail.Should().Be("The Description field is required."); - error3.Source.ShouldNotBeNull(); + error3.Source.Should().NotBeNull(); error3.Source.Pointer.Should().Be("/data/attributes/description"); store.SqlCommands.Should().BeEmpty(); @@ -357,10 +357,10 @@ public async Task Can_create_resource_with_unmapped_property() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - AccountRecovery existingAccountRecovery = _fakers.AccountRecovery.Generate(); - Person existingPerson = _fakers.Person.Generate(); + AccountRecovery existingAccountRecovery = _fakers.AccountRecovery.GenerateOne(); + Person existingPerson = _fakers.Person.GenerateOne(); - string newUserName = _fakers.LoginAccount.Generate().UserName; + string newUserName = _fakers.LoginAccount.GenerateOne().UserName; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -407,13 +407,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("loginAccounts"); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("userName").With(value => value.Should().Be(newUserName)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("userName").WhoseValue.Should().Be(newUserName); responseDocument.Data.SingleValue.Attributes.Should().NotContainKey("lastUsedAt"); - responseDocument.Data.SingleValue.Relationships.ShouldOnlyContainKeys("recovery", "person"); + responseDocument.Data.SingleValue.Relationships.Should().OnlyContainKeys("recovery", "person"); - long newLoginAccountId = long.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + long newLoginAccountId = long.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -431,13 +431,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => loginAccountInDatabase.UserName.Should().Be(newUserName); loginAccountInDatabase.LastUsedAt.Should().BeNull(); - loginAccountInDatabase.Recovery.ShouldNotBeNull(); + loginAccountInDatabase.Recovery.Should().NotBeNull(); loginAccountInDatabase.Recovery.Id.Should().Be(existingAccountRecovery.Id); - loginAccountInDatabase.Person.ShouldNotBeNull(); + loginAccountInDatabase.Person.Should().NotBeNull(); loginAccountInDatabase.Person.Id.Should().Be(existingPerson.Id); }); - store.SqlCommands.ShouldHaveCount(4); + store.SqlCommands.Should().HaveCount(4); store.SqlCommands[0].With(command => { @@ -446,7 +446,7 @@ DELETE FROM "LoginAccounts" WHERE "RecoveryId" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingAccountRecovery.Id); }); @@ -458,7 +458,7 @@ DELETE FROM "LoginAccounts" RETURNING "Id" """)); - command.Parameters.ShouldHaveCount(3); + command.Parameters.Should().HaveCount(3); command.Parameters.Should().Contain("@p1", newUserName); command.Parameters.Should().Contain("@p2", null); command.Parameters.Should().Contain("@p3", existingAccountRecovery.Id); @@ -472,7 +472,7 @@ DELETE FROM "LoginAccounts" WHERE "Id" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", newLoginAccountId); command.Parameters.Should().Contain("@p2", existingPerson.Id); }); @@ -485,7 +485,7 @@ DELETE FROM "LoginAccounts" WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", newLoginAccountId); }); } @@ -497,7 +497,7 @@ public async Task Can_create_resource_with_calculated_attribute() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person newPerson = _fakers.Person.Generate(); + Person newPerson = _fakers.Person.GenerateOne(); var requestBody = new { @@ -520,14 +520,14 @@ public async Task Can_create_resource_with_calculated_attribute() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("people"); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("firstName").With(value => value.Should().Be(newPerson.FirstName)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("lastName").With(value => value.Should().Be(newPerson.LastName)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("displayName").With(value => value.Should().Be(newPerson.DisplayName)); - responseDocument.Data.SingleValue.Relationships.ShouldOnlyContainKeys("account", "ownedTodoItems", "assignedTodoItems"); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("firstName").WhoseValue.Should().Be(newPerson.FirstName); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("lastName").WhoseValue.Should().Be(newPerson.LastName); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("displayName").WhoseValue.Should().Be(newPerson.DisplayName); + responseDocument.Data.SingleValue.Relationships.Should().OnlyContainKeys("account", "ownedTodoItems", "assignedTodoItems"); - long newPersonId = long.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + long newPersonId = long.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -538,7 +538,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => personInDatabase.DisplayName.Should().Be(newPerson.DisplayName); }); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -548,7 +548,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => RETURNING "Id" """)); - command.Parameters.ShouldHaveCount(3); + command.Parameters.Should().HaveCount(3); command.Parameters.Should().Contain("@p1", newPerson.FirstName); command.Parameters.Should().Contain("@p2", newPerson.LastName); command.Parameters.Should().Contain("@p3", null); @@ -562,7 +562,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", newPersonId); }); } @@ -574,9 +574,9 @@ public async Task Can_create_resource_with_client_generated_ID() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Tag existingTag = _fakers.Tag.Generate(); + Tag existingTag = _fakers.Tag.GenerateOne(); - RgbColor newColor = _fakers.RgbColor.Generate(); + RgbColor newColor = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -623,11 +623,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => colorInDatabase.Green.Should().Be(newColor.Green); colorInDatabase.Blue.Should().Be(newColor.Blue); - colorInDatabase.Tag.ShouldNotBeNull(); + colorInDatabase.Tag.Should().NotBeNull(); colorInDatabase.Tag.Id.Should().Be(existingTag.Id); }); - store.SqlCommands.ShouldHaveCount(3); + store.SqlCommands.Should().HaveCount(3); store.SqlCommands[0].With(command => { @@ -636,7 +636,7 @@ DELETE FROM "RgbColors" WHERE "TagId" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingTag.Id); }); @@ -648,7 +648,7 @@ DELETE FROM "RgbColors" RETURNING "Id" """, true)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", newColor.Id); command.Parameters.Should().Contain("@p2", existingTag.Id); }); @@ -661,7 +661,7 @@ SELECT t1."Id" WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", newColor.Id); }); } @@ -673,10 +673,10 @@ public async Task Cannot_create_resource_for_existing_client_generated_ID() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - RgbColor existingColor = _fakers.RgbColor.Generate(); - existingColor.Tag = _fakers.Tag.Generate(); + RgbColor existingColor = _fakers.RgbColor.GenerateOne(); + existingColor.Tag = _fakers.Tag.GenerateOne(); - Tag existingTag = _fakers.Tag.Generate(); + Tag existingTag = _fakers.Tag.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -713,7 +713,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); @@ -721,7 +721,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => error.Detail.Should().Be($"Another resource of type 'rgbColors' with ID '{existingColor.StringId}' already exists."); error.Source.Should().BeNull(); - store.SqlCommands.ShouldHaveCount(3); + store.SqlCommands.Should().HaveCount(3); store.SqlCommands[0].With(command => { @@ -730,7 +730,7 @@ DELETE FROM "RgbColors" WHERE "TagId" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingTag.Id); }); @@ -742,7 +742,7 @@ DELETE FROM "RgbColors" RETURNING "Id" """, true)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", existingColor.Id); command.Parameters.Should().Contain("@p2", existingTag.Id); }); @@ -755,7 +755,7 @@ SELECT t1."Id" WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingColor.Id); }); } diff --git a/test/DapperTests/IntegrationTests/ReadWrite/Resources/DeleteResourceTests.cs b/test/DapperTests/IntegrationTests/ReadWrite/Resources/DeleteResourceTests.cs index af81d138a6..566c546c73 100644 --- a/test/DapperTests/IntegrationTests/ReadWrite/Resources/DeleteResourceTests.cs +++ b/test/DapperTests/IntegrationTests/ReadWrite/Resources/DeleteResourceTests.cs @@ -29,10 +29,10 @@ public async Task Can_delete_resource() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem existingTodoItem = _fakers.TodoItem.Generate(); - existingTodoItem.Owner = _fakers.Person.Generate(); - existingTodoItem.Tags = _fakers.Tag.Generate(1).ToHashSet(); - existingTodoItem.Tags.ElementAt(0).Color = _fakers.RgbColor.Generate(); + TodoItem existingTodoItem = _fakers.TodoItem.GenerateOne(); + existingTodoItem.Owner = _fakers.Person.GenerateOne(); + existingTodoItem.Tags = _fakers.Tag.GenerateSet(1); + existingTodoItem.Tags.ElementAt(0).Color = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -59,10 +59,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => List tags = await dbContext.Tags.Where(tag => tag.TodoItem == null).ToListAsync(); - tags.ShouldHaveCount(1); + tags.Should().HaveCount(1); }); - store.SqlCommands.ShouldHaveCount(1); + store.SqlCommands.Should().HaveCount(1); store.SqlCommands[0].With(command => { @@ -71,7 +71,7 @@ DELETE FROM "TodoItems" WHERE "Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingTodoItem.Id); }); } @@ -93,7 +93,7 @@ public async Task Cannot_delete_unknown_resource() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -101,7 +101,7 @@ public async Task Cannot_delete_unknown_resource() error.Detail.Should().Be($"Resource of type 'todoItems' with ID '{unknownTodoItemId}' does not exist."); error.Source.Should().BeNull(); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -110,7 +110,7 @@ DELETE FROM "TodoItems" WHERE "Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", unknownTodoItemId); }); @@ -122,7 +122,7 @@ SELECT t1."Id" WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", unknownTodoItemId); }); } diff --git a/test/DapperTests/IntegrationTests/ReadWrite/Resources/FetchResourceTests.cs b/test/DapperTests/IntegrationTests/ReadWrite/Resources/FetchResourceTests.cs index 0027de1d38..bd7139e5c4 100644 --- a/test/DapperTests/IntegrationTests/ReadWrite/Resources/FetchResourceTests.cs +++ b/test/DapperTests/IntegrationTests/ReadWrite/Resources/FetchResourceTests.cs @@ -28,8 +28,8 @@ public async Task Can_get_primary_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - List todoItems = _fakers.TodoItem.Generate(2); - todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.Generate()); + List todoItems = _fakers.TodoItem.GenerateList(2); + todoItems.ForEach(todoItem => todoItem.Owner = _fakers.Person.GenerateOne()); todoItems[0].Priority = TodoItemPriority.Low; todoItems[1].Priority = TodoItemPriority.High; @@ -49,28 +49,28 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue.Should().AllSatisfy(resource => resource.Type.Should().Be("todoItems")); responseDocument.Data.ManyValue[0].Id.Should().Be(todoItems[1].StringId); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("description").With(value => value.Should().Be(todoItems[1].Description)); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("priority").With(value => value.Should().Be(todoItems[1].Priority)); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("durationInHours").With(value => value.Should().Be(todoItems[1].DurationInHours)); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("createdAt").With(value => value.Should().Be(todoItems[1].CreatedAt)); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("modifiedAt").With(value => value.Should().Be(todoItems[1].LastModifiedAt)); - responseDocument.Data.ManyValue[0].Relationships.ShouldOnlyContainKeys("owner", "assignee", "tags"); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("description").WhoseValue.Should().Be(todoItems[1].Description); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("priority").WhoseValue.Should().Be(todoItems[1].Priority); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("durationInHours").WhoseValue.Should().Be(todoItems[1].DurationInHours); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("createdAt").WhoseValue.Should().Be(todoItems[1].CreatedAt); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("modifiedAt").WhoseValue.Should().Be(todoItems[1].LastModifiedAt); + responseDocument.Data.ManyValue[0].Relationships.Should().OnlyContainKeys("owner", "assignee", "tags"); responseDocument.Data.ManyValue[1].Id.Should().Be(todoItems[0].StringId); - responseDocument.Data.ManyValue[1].Attributes.ShouldContainKey("description").With(value => value.Should().Be(todoItems[0].Description)); - responseDocument.Data.ManyValue[1].Attributes.ShouldContainKey("priority").With(value => value.Should().Be(todoItems[0].Priority)); - responseDocument.Data.ManyValue[1].Attributes.ShouldContainKey("durationInHours").With(value => value.Should().Be(todoItems[0].DurationInHours)); - responseDocument.Data.ManyValue[1].Attributes.ShouldContainKey("createdAt").With(value => value.Should().Be(todoItems[0].CreatedAt)); - responseDocument.Data.ManyValue[1].Attributes.ShouldContainKey("modifiedAt").With(value => value.Should().Be(todoItems[0].LastModifiedAt)); - responseDocument.Data.ManyValue[1].Relationships.ShouldOnlyContainKeys("owner", "assignee", "tags"); + responseDocument.Data.ManyValue[1].Attributes.Should().ContainKey("description").WhoseValue.Should().Be(todoItems[0].Description); + responseDocument.Data.ManyValue[1].Attributes.Should().ContainKey("priority").WhoseValue.Should().Be(todoItems[0].Priority); + responseDocument.Data.ManyValue[1].Attributes.Should().ContainKey("durationInHours").WhoseValue.Should().Be(todoItems[0].DurationInHours); + responseDocument.Data.ManyValue[1].Attributes.Should().ContainKey("createdAt").WhoseValue.Should().Be(todoItems[0].CreatedAt); + responseDocument.Data.ManyValue[1].Attributes.Should().ContainKey("modifiedAt").WhoseValue.Should().Be(todoItems[0].LastModifiedAt); + responseDocument.Data.ManyValue[1].Relationships.Should().OnlyContainKeys("owner", "assignee", "tags"); responseDocument.Meta.Should().ContainTotal(2); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -101,8 +101,8 @@ public async Task Can_get_primary_resource_by_ID() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -118,19 +118,19 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("todoItems"); responseDocument.Data.SingleValue.Id.Should().Be(todoItem.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("description").With(value => value.Should().Be(todoItem.Description)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("priority").With(value => value.Should().Be(todoItem.Priority)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("durationInHours").With(value => value.Should().Be(todoItem.DurationInHours)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("createdAt").With(value => value.Should().Be(todoItem.CreatedAt)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("modifiedAt").With(value => value.Should().Be(todoItem.LastModifiedAt)); - responseDocument.Data.SingleValue.Relationships.ShouldOnlyContainKeys("owner", "assignee", "tags"); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("description").WhoseValue.Should().Be(todoItem.Description); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("priority").WhoseValue.Should().Be(todoItem.Priority); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("durationInHours").WhoseValue.Should().Be(todoItem.DurationInHours); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("createdAt").WhoseValue.Should().Be(todoItem.CreatedAt); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("modifiedAt").WhoseValue.Should().Be(todoItem.LastModifiedAt); + responseDocument.Data.SingleValue.Relationships.Should().OnlyContainKeys("owner", "assignee", "tags"); responseDocument.Meta.Should().BeNull(); - store.SqlCommands.ShouldHaveCount(1); + store.SqlCommands.Should().HaveCount(1); store.SqlCommands[0].With(command => { @@ -140,7 +140,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", todoItem.Id); }); } @@ -162,7 +162,7 @@ public async Task Cannot_get_unknown_primary_resource_by_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -170,7 +170,7 @@ public async Task Cannot_get_unknown_primary_resource_by_ID() error.Detail.Should().Be($"Resource of type 'todoItems' with ID '{unknownTodoItemId}' does not exist."); error.Source.Should().BeNull(); - store.SqlCommands.ShouldHaveCount(1); + store.SqlCommands.Should().HaveCount(1); store.SqlCommands[0].With(command => { @@ -180,7 +180,7 @@ public async Task Cannot_get_unknown_primary_resource_by_ID() WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", unknownTodoItemId); }); } @@ -192,9 +192,9 @@ public async Task Can_get_secondary_ToMany_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); - todoItem.Tags = _fakers.Tag.Generate(2).ToHashSet(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); + todoItem.Tags = _fakers.Tag.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -211,20 +211,20 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue.Should().AllSatisfy(resource => resource.Type.Should().Be("tags")); responseDocument.Data.ManyValue[0].Id.Should().Be(todoItem.Tags.ElementAt(0).StringId); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("name").With(value => value.Should().Be(todoItem.Tags.ElementAt(0).Name)); - responseDocument.Data.ManyValue[0].Relationships.ShouldOnlyContainKeys("todoItem", "color"); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("name").WhoseValue.Should().Be(todoItem.Tags.ElementAt(0).Name); + responseDocument.Data.ManyValue[0].Relationships.Should().OnlyContainKeys("todoItem", "color"); responseDocument.Data.ManyValue[1].Id.Should().Be(todoItem.Tags.ElementAt(1).StringId); - responseDocument.Data.ManyValue[1].Attributes.ShouldContainKey("name").With(value => value.Should().Be(todoItem.Tags.ElementAt(1).Name)); - responseDocument.Data.ManyValue[1].Relationships.ShouldOnlyContainKeys("todoItem", "color"); + responseDocument.Data.ManyValue[1].Attributes.Should().ContainKey("name").WhoseValue.Should().Be(todoItem.Tags.ElementAt(1).Name); + responseDocument.Data.ManyValue[1].Relationships.Should().OnlyContainKeys("todoItem", "color"); responseDocument.Meta.Should().ContainTotal(2); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -235,7 +235,7 @@ SELECT COUNT(*) WHERE t2."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", todoItem.Id); }); @@ -249,7 +249,7 @@ SELECT COUNT(*) ORDER BY t2."Id" """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", todoItem.Id); }); } @@ -261,8 +261,8 @@ public async Task Can_get_secondary_ToOne_resource() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -278,17 +278,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("people"); responseDocument.Data.SingleValue.Id.Should().Be(todoItem.Owner.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("firstName").With(value => value.Should().Be(todoItem.Owner.FirstName)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("lastName").With(value => value.Should().Be(todoItem.Owner.LastName)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("displayName").With(value => value.Should().Be(todoItem.Owner.DisplayName)); - responseDocument.Data.SingleValue.Relationships.ShouldOnlyContainKeys("account", "ownedTodoItems", "assignedTodoItems"); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("firstName").WhoseValue.Should().Be(todoItem.Owner.FirstName); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("lastName").WhoseValue.Should().Be(todoItem.Owner.LastName); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("displayName").WhoseValue.Should().Be(todoItem.Owner.DisplayName); + responseDocument.Data.SingleValue.Relationships.Should().OnlyContainKeys("account", "ownedTodoItems", "assignedTodoItems"); responseDocument.Meta.Should().BeNull(); - store.SqlCommands.ShouldHaveCount(1); + store.SqlCommands.Should().HaveCount(1); store.SqlCommands[0].With(command => { @@ -299,7 +299,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", todoItem.Id); }); } @@ -311,8 +311,8 @@ public async Task Can_get_empty_secondary_ToOne_resource() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -332,7 +332,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Meta.Should().BeNull(); - store.SqlCommands.ShouldHaveCount(1); + store.SqlCommands.Should().HaveCount(1); store.SqlCommands[0].With(command => { @@ -343,7 +343,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", todoItem.Id); }); } diff --git a/test/DapperTests/IntegrationTests/ReadWrite/Resources/UpdateResourceTests.cs b/test/DapperTests/IntegrationTests/ReadWrite/Resources/UpdateResourceTests.cs index f51b7c6b52..dc8bccf5ee 100644 --- a/test/DapperTests/IntegrationTests/ReadWrite/Resources/UpdateResourceTests.cs +++ b/test/DapperTests/IntegrationTests/ReadWrite/Resources/UpdateResourceTests.cs @@ -29,8 +29,8 @@ public async Task Can_update_resource_without_attributes_or_relationships() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Tag existingTag = _fakers.Tag.Generate(); - existingTag.Color = _fakers.RgbColor.Generate(); + Tag existingTag = _fakers.Tag.GenerateOne(); + existingTag.Color = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -69,11 +69,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => Tag tagInDatabase = await dbContext.Tags.Include(tag => tag.Color).FirstWithIdAsync(existingTag.Id); tagInDatabase.Name.Should().Be(existingTag.Name); - tagInDatabase.Color.ShouldNotBeNull(); + tagInDatabase.Color.Should().NotBeNull(); tagInDatabase.Color.Id.Should().Be(existingTag.Color.Id); }); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -83,7 +83,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingTag.Id); }); @@ -95,7 +95,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingTag.Id); }); } @@ -107,13 +107,13 @@ public async Task Can_partially_update_resource_attributes() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem existingTodoItem = _fakers.TodoItem.Generate(); - existingTodoItem.Owner = _fakers.Person.Generate(); - existingTodoItem.Assignee = _fakers.Person.Generate(); - existingTodoItem.Tags = _fakers.Tag.Generate(1).ToHashSet(); + TodoItem existingTodoItem = _fakers.TodoItem.GenerateOne(); + existingTodoItem.Owner = _fakers.Person.GenerateOne(); + existingTodoItem.Assignee = _fakers.Person.GenerateOne(); + existingTodoItem.Tags = _fakers.Tag.GenerateSet(1); - string newDescription = _fakers.TodoItem.Generate().Description; - long newDurationInHours = _fakers.TodoItem.Generate().DurationInHours!.Value; + string newDescription = _fakers.TodoItem.GenerateOne().Description; + long newDurationInHours = _fakers.TodoItem.GenerateOne().DurationInHours!.Value; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -143,15 +143,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("todoItems"); responseDocument.Data.SingleValue.Id.Should().Be(existingTodoItem.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("description").With(value => value.Should().Be(newDescription)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("priority").With(value => value.Should().Be(existingTodoItem.Priority)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("durationInHours").With(value => value.Should().Be(newDurationInHours)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("createdAt").With(value => value.Should().Be(existingTodoItem.CreatedAt)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("modifiedAt").With(value => value.Should().Be(DapperTestContext.FrozenTime)); - responseDocument.Data.SingleValue.Relationships.ShouldOnlyContainKeys("owner", "assignee", "tags"); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("description").WhoseValue.Should().Be(newDescription); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("priority").WhoseValue.Should().Be(existingTodoItem.Priority); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("durationInHours").WhoseValue.Should().Be(newDurationInHours); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("createdAt").WhoseValue.Should().Be(existingTodoItem.CreatedAt); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("modifiedAt").WhoseValue.Should().Be(DapperTestContext.FrozenTime); + responseDocument.Data.SingleValue.Relationships.Should().OnlyContainKeys("owner", "assignee", "tags"); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -173,15 +173,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => todoItemInDatabase.CreatedAt.Should().Be(existingTodoItem.CreatedAt); todoItemInDatabase.LastModifiedAt.Should().Be(DapperTestContext.FrozenTime); - todoItemInDatabase.Owner.ShouldNotBeNull(); + todoItemInDatabase.Owner.Should().NotBeNull(); todoItemInDatabase.Owner.Id.Should().Be(existingTodoItem.Owner.Id); - todoItemInDatabase.Assignee.ShouldNotBeNull(); + todoItemInDatabase.Assignee.Should().NotBeNull(); todoItemInDatabase.Assignee.Id.Should().Be(existingTodoItem.Assignee.Id); - todoItemInDatabase.Tags.ShouldHaveCount(1); + todoItemInDatabase.Tags.Should().HaveCount(1); todoItemInDatabase.Tags.ElementAt(0).Id.Should().Be(existingTodoItem.Tags.ElementAt(0).Id); }); - store.SqlCommands.ShouldHaveCount(3); + store.SqlCommands.Should().HaveCount(3); store.SqlCommands[0].With(command => { @@ -191,7 +191,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingTodoItem.Id); }); @@ -203,7 +203,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" = @p4 """)); - command.Parameters.ShouldHaveCount(4); + command.Parameters.Should().HaveCount(4); command.Parameters.Should().Contain("@p1", newDescription); command.Parameters.Should().Contain("@p2", newDurationInHours); command.Parameters.Should().Contain("@p3", DapperTestContext.FrozenTime); @@ -218,7 +218,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingTodoItem.Id); }); } @@ -230,16 +230,16 @@ public async Task Can_completely_update_resource() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem existingTodoItem = _fakers.TodoItem.Generate(); - existingTodoItem.Owner = _fakers.Person.Generate(); - existingTodoItem.Assignee = _fakers.Person.Generate(); - existingTodoItem.Tags = _fakers.Tag.Generate(2).ToHashSet(); + TodoItem existingTodoItem = _fakers.TodoItem.GenerateOne(); + existingTodoItem.Owner = _fakers.Person.GenerateOne(); + existingTodoItem.Assignee = _fakers.Person.GenerateOne(); + existingTodoItem.Tags = _fakers.Tag.GenerateSet(2); - TodoItem newTodoItem = _fakers.TodoItem.Generate(); + TodoItem newTodoItem = _fakers.TodoItem.GenerateOne(); - Tag existingTag = _fakers.Tag.Generate(); - Person existingPerson1 = _fakers.Person.Generate(); - Person existingPerson2 = _fakers.Person.Generate(); + Tag existingTag = _fakers.Tag.GenerateOne(); + Person existingPerson1 = _fakers.Person.GenerateOne(); + Person existingPerson2 = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -300,15 +300,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("todoItems"); responseDocument.Data.SingleValue.Id.Should().Be(existingTodoItem.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("description").With(value => value.Should().Be(newTodoItem.Description)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("priority").With(value => value.Should().Be(newTodoItem.Priority)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("durationInHours").With(value => value.Should().Be(newTodoItem.DurationInHours)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("createdAt").With(value => value.Should().Be(existingTodoItem.CreatedAt)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("modifiedAt").With(value => value.Should().Be(DapperTestContext.FrozenTime)); - responseDocument.Data.SingleValue.Relationships.ShouldOnlyContainKeys("owner", "assignee", "tags"); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("description").WhoseValue.Should().Be(newTodoItem.Description); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("priority").WhoseValue.Should().Be(newTodoItem.Priority); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("durationInHours").WhoseValue.Should().Be(newTodoItem.DurationInHours); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("createdAt").WhoseValue.Should().Be(existingTodoItem.CreatedAt); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("modifiedAt").WhoseValue.Should().Be(DapperTestContext.FrozenTime); + responseDocument.Data.SingleValue.Relationships.Should().OnlyContainKeys("owner", "assignee", "tags"); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -330,15 +330,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => todoItemInDatabase.CreatedAt.Should().Be(existingTodoItem.CreatedAt); todoItemInDatabase.LastModifiedAt.Should().Be(DapperTestContext.FrozenTime); - todoItemInDatabase.Owner.ShouldNotBeNull(); + todoItemInDatabase.Owner.Should().NotBeNull(); todoItemInDatabase.Owner.Id.Should().Be(existingPerson1.Id); - todoItemInDatabase.Assignee.ShouldNotBeNull(); + todoItemInDatabase.Assignee.Should().NotBeNull(); todoItemInDatabase.Assignee.Id.Should().Be(existingPerson2.Id); - todoItemInDatabase.Tags.ShouldHaveCount(1); + todoItemInDatabase.Tags.Should().HaveCount(1); todoItemInDatabase.Tags.ElementAt(0).Id.Should().Be(existingTag.Id); }); - store.SqlCommands.ShouldHaveCount(5); + store.SqlCommands.Should().HaveCount(5); store.SqlCommands[0].With(command => { @@ -351,7 +351,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingTodoItem.Id); }); @@ -363,7 +363,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" = @p7 """)); - command.Parameters.ShouldHaveCount(7); + command.Parameters.Should().HaveCount(7); command.Parameters.Should().Contain("@p1", newTodoItem.Description); command.Parameters.Should().Contain("@p2", newTodoItem.Priority); command.Parameters.Should().Contain("@p3", newTodoItem.DurationInHours); @@ -381,7 +381,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" IN (@p2, @p3) """)); - command.Parameters.ShouldHaveCount(3); + command.Parameters.Should().HaveCount(3); command.Parameters.Should().Contain("@p1", null); command.Parameters.Should().Contain("@p2", existingTodoItem.Tags.ElementAt(0).Id); command.Parameters.Should().Contain("@p3", existingTodoItem.Tags.ElementAt(1).Id); @@ -395,7 +395,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE "Id" = @p2 """)); - command.Parameters.ShouldHaveCount(2); + command.Parameters.Should().HaveCount(2); command.Parameters.Should().Contain("@p1", existingTodoItem.Id); command.Parameters.Should().Contain("@p2", existingTag.Id); }); @@ -408,7 +408,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WHERE t1."Id" = @p1 """)); - command.Parameters.ShouldHaveCount(1); + command.Parameters.Should().HaveCount(1); command.Parameters.Should().Contain("@p1", existingTodoItem.Id); }); } diff --git a/test/DapperTests/IntegrationTests/Sql/SubQueryInJoinTests.cs b/test/DapperTests/IntegrationTests/Sql/SubQueryInJoinTests.cs index ed75d24d65..8b7d18d2d2 100644 --- a/test/DapperTests/IntegrationTests/Sql/SubQueryInJoinTests.cs +++ b/test/DapperTests/IntegrationTests/Sql/SubQueryInJoinTests.cs @@ -27,7 +27,7 @@ public async Task Join_with_table_on_ToOne_include() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -44,7 +44,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -76,7 +76,7 @@ public async Task Join_with_table_on_ToMany_include() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -93,7 +93,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -125,7 +125,7 @@ public async Task Join_with_table_on_ToMany_include_with_nested_sort_on_attribut var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -142,7 +142,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -174,7 +174,7 @@ public async Task Join_with_table_on_ToMany_include_with_nested_sort_on_count() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -191,7 +191,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -227,7 +227,7 @@ public async Task Join_with_tables_on_includes_with_nested_sorts() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -244,7 +244,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -281,8 +281,8 @@ public async Task Join_with_tables_on_includes_with_nested_sorts_on_counts() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - TodoItem todoItem = _fakers.TodoItem.Generate(); - todoItem.Owner = _fakers.Person.Generate(); + TodoItem todoItem = _fakers.TodoItem.GenerateOne(); + todoItem.Owner = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -300,7 +300,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -344,7 +344,7 @@ public async Task Join_with_sub_query_on_ToMany_include_with_nested_filter() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -361,7 +361,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -398,7 +398,7 @@ public async Task Join_with_sub_query_on_ToMany_include_with_nested_filter_on_ha var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -415,7 +415,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -455,7 +455,7 @@ public async Task Join_with_sub_query_on_ToMany_include_with_nested_filter_on_co var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -472,7 +472,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -513,7 +513,7 @@ public async Task Join_with_sub_query_on_includes_with_nested_filter_and_sorts() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -531,7 +531,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { @@ -573,7 +573,7 @@ public async Task Join_with_nested_sub_queries_with_filters_and_sorts() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Person person = _fakers.Person.Generate(); + Person person = _fakers.Person.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -592,7 +592,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - store.SqlCommands.ShouldHaveCount(2); + store.SqlCommands.Should().HaveCount(2); store.SqlCommands[0].With(command => { diff --git a/test/DapperTests/IntegrationTests/SqlTextAdapter.cs b/test/DapperTests/IntegrationTests/SqlTextAdapter.cs index de860f5814..1d6d45555e 100644 --- a/test/DapperTests/IntegrationTests/SqlTextAdapter.cs +++ b/test/DapperTests/IntegrationTests/SqlTextAdapter.cs @@ -5,10 +5,12 @@ namespace DapperTests.IntegrationTests; internal sealed class SqlTextAdapter(DatabaseProvider databaseProvider) { + private const RegexOptions Options = RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.NonBacktracking; + private static readonly Dictionary SqlServerReplacements = new() { - [new Regex("\"([^\"]+)\"", RegexOptions.Compiled)] = "[$+]", - [new Regex($@"(VALUES \([^)]*\)){Environment.NewLine}RETURNING \[Id\]", RegexOptions.Compiled)] = $"OUTPUT INSERTED.[Id]{Environment.NewLine}$1" + [new Regex("\"([^\"]+)\"", Options)] = "[$+]", + [new Regex($@"(VALUES \([^)]*\)){Environment.NewLine}RETURNING \[Id\]", Options)] = $"OUTPUT INSERTED.[Id]{Environment.NewLine}$1" }; private readonly DatabaseProvider _databaseProvider = databaseProvider; diff --git a/test/DapperTests/UnitTests/LogicalCombinatorTests.cs b/test/DapperTests/UnitTests/LogicalCombinatorTests.cs index 065cec7dd6..de400c4f30 100644 --- a/test/DapperTests/UnitTests/LogicalCombinatorTests.cs +++ b/test/DapperTests/UnitTests/LogicalCombinatorTests.cs @@ -43,7 +43,7 @@ public void Collapses_and_filters() conditionRight3 }.Select(condition => condition.ToString()); - string expectedText = '(' + string.Join(") AND (", terms) + ')'; + string expectedText = $"({string.Join(") AND (", terms)})"; result.ToString().Should().Be(expectedText); } } diff --git a/test/DapperTests/UnitTests/ParameterNodeTests.cs b/test/DapperTests/UnitTests/ParameterNodeTests.cs index 497e72d447..e199783fd1 100644 --- a/test/DapperTests/UnitTests/ParameterNodeTests.cs +++ b/test/DapperTests/UnitTests/ParameterNodeTests.cs @@ -40,6 +40,6 @@ public void Can_format_parameter(object? parameterValue, string formattedValueEx string text = parameter.ToString(); // Assert - text.Should().Be("@name = " + formattedValueExpected); + text.Should().Be($"@name = {formattedValueExpected}"); } } diff --git a/test/DiscoveryTests/AspNetOpenApiTests.cs b/test/DiscoveryTests/AspNetOpenApiTests.cs new file mode 100644 index 0000000000..20619f4cc1 --- /dev/null +++ b/test/DiscoveryTests/AspNetOpenApiTests.cs @@ -0,0 +1,31 @@ +#if !NET8_0 +using FluentAssertions; +using JsonApiDotNetCore.Configuration; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace DiscoveryTests; + +public sealed class AspNetOpenApiTests +{ + [Fact] + public async Task Throws_when_AspNet_OpenApi_is_registered() + { + // Arrange + WebApplicationBuilder builder = WebApplication.CreateEmptyBuilder(new WebApplicationOptions()); + builder.WebHost.UseTestServer(); + builder.Services.AddJsonApi(); + builder.Services.AddOpenApi(); + await using WebApplication app = builder.Build(); + + // Act + Action action = app.UseJsonApi; + + // Assert + action.Should().ThrowExactly().WithMessage("JsonApiDotNetCore is incompatible with ASP.NET OpenAPI. " + + "Replace 'services.AddOpenApi()' with 'services.AddOpenApiForJsonApi()' from the JsonApiDotNetCore.OpenApi.Swashbuckle NuGet package."); + } +} +#endif diff --git a/test/DiscoveryTests/DiscoveryTests.csproj b/test/DiscoveryTests/DiscoveryTests.csproj index a64d3be689..825056684e 100644 --- a/test/DiscoveryTests/DiscoveryTests.csproj +++ b/test/DiscoveryTests/DiscoveryTests.csproj @@ -1,6 +1,6 @@ - net8.0;net6.0 + net9.0;net8.0 @@ -14,5 +14,6 @@ + diff --git a/test/DiscoveryTests/PrivateResourceDefinition.cs b/test/DiscoveryTests/PrivateResourceDefinition.cs index 80883eaa6d..3003ce389c 100644 --- a/test/DiscoveryTests/PrivateResourceDefinition.cs +++ b/test/DiscoveryTests/PrivateResourceDefinition.cs @@ -5,4 +5,5 @@ namespace DiscoveryTests; [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] -public sealed class PrivateResourceDefinition(IResourceGraph resourceGraph) : JsonApiResourceDefinition(resourceGraph); +public sealed class PrivateResourceDefinition(IResourceGraph resourceGraph) + : JsonApiResourceDefinition(resourceGraph); diff --git a/test/DiscoveryTests/PrivateResourceService.cs b/test/DiscoveryTests/PrivateResourceService.cs index 751d04baab..bad4b41428 100644 --- a/test/DiscoveryTests/PrivateResourceService.cs +++ b/test/DiscoveryTests/PrivateResourceService.cs @@ -13,5 +13,6 @@ namespace DiscoveryTests; public sealed class PrivateResourceService( IResourceRepositoryAccessor repositoryAccessor, IQueryLayerComposer queryLayerComposer, IPaginationContext paginationContext, IJsonApiOptions options, ILoggerFactory loggerFactory, IJsonApiRequest request, IResourceChangeTracker resourceChangeTracker, - IResourceDefinitionAccessor resourceDefinitionAccessor) : JsonApiResourceService(repositoryAccessor, queryLayerComposer, - paginationContext, options, loggerFactory, request, resourceChangeTracker, resourceDefinitionAccessor); + IResourceDefinitionAccessor resourceDefinitionAccessor) + : JsonApiResourceService(repositoryAccessor, queryLayerComposer, paginationContext, options, loggerFactory, request, + resourceChangeTracker, resourceDefinitionAccessor); diff --git a/test/DiscoveryTests/ServiceDiscoveryFacadeTests.cs b/test/DiscoveryTests/ServiceDiscoveryFacadeTests.cs index e4f16dbb1f..eeca3cdb89 100644 --- a/test/DiscoveryTests/ServiceDiscoveryFacadeTests.cs +++ b/test/DiscoveryTests/ServiceDiscoveryFacadeTests.cs @@ -8,7 +8,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -using TestBuildingBlocks; using Xunit; namespace DiscoveryTests; @@ -37,10 +36,10 @@ public void Can_add_resources_from_assembly_to_graph() var resourceGraph = serviceProvider.GetRequiredService(); ResourceType? personType = resourceGraph.FindResourceType(typeof(Person)); - personType.ShouldNotBeNull(); + personType.Should().NotBeNull(); ResourceType? todoItemType = resourceGraph.FindResourceType(typeof(TodoItem)); - todoItemType.ShouldNotBeNull(); + todoItemType.Should().NotBeNull(); } [Fact] @@ -57,7 +56,7 @@ public void Can_add_resource_from_current_assembly_to_graph() var resourceGraph = serviceProvider.GetRequiredService(); ResourceType? resourceType = resourceGraph.FindResourceType(typeof(PrivateResource)); - resourceType.ShouldNotBeNull(); + resourceType.Should().NotBeNull(); } [Fact] diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Archiving/ArchiveTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Archiving/ArchiveTests.cs index 6b400325e3..97506ec5d6 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Archiving/ArchiveTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Archiving/ArchiveTests.cs @@ -28,7 +28,7 @@ public ArchiveTests(IntegrationTestContext, public async Task Can_get_archived_resource_by_ID() { // Arrange - TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.Generate(); + TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -44,16 +44,16 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(broadcast.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("archivedAt").With(value => value.Should().Be(broadcast.ArchivedAt)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("archivedAt").WhoseValue.Should().Be(broadcast.ArchivedAt); } [Fact] public async Task Can_get_unarchived_resource_by_ID() { // Arrange - TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.Generate(); + TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.GenerateOne(); broadcast.ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -70,16 +70,16 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(broadcast.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("archivedAt").With(value => value.Should().BeNull()); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("archivedAt").WhoseValue.Should().BeNull(); } [Fact] public async Task Get_primary_resources_excludes_archived() { // Arrange - List broadcasts = _fakers.TelevisionBroadcast.Generate(2); + List broadcasts = _fakers.TelevisionBroadcast.GenerateList(2); broadcasts[1].ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -97,16 +97,16 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(broadcasts[1].StringId); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("archivedAt").With(value => value.Should().BeNull()); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("archivedAt").WhoseValue.Should().BeNull(); } [Fact] public async Task Get_primary_resources_with_filter_includes_archived() { // Arrange - List broadcasts = _fakers.TelevisionBroadcast.Generate(2); + List broadcasts = _fakers.TelevisionBroadcast.GenerateList(2); broadcasts[1].ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -124,20 +124,20 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue[0].Id.Should().Be(broadcasts[0].StringId); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("archivedAt").With(value => value.Should().Be(broadcasts[0].ArchivedAt)); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("archivedAt").WhoseValue.Should().Be(broadcasts[0].ArchivedAt); responseDocument.Data.ManyValue[1].Id.Should().Be(broadcasts[1].StringId); - responseDocument.Data.ManyValue[1].Attributes.ShouldContainKey("archivedAt").With(value => value.Should().BeNull()); + responseDocument.Data.ManyValue[1].Attributes.Should().ContainKey("archivedAt").WhoseValue.Should().BeNull(); } [Fact] public async Task Get_primary_resource_by_ID_with_include_excludes_archived() { // Arrange - TelevisionStation station = _fakers.TelevisionStation.Generate(); - station.Broadcasts = _fakers.TelevisionBroadcast.Generate(2).ToHashSet(); + TelevisionStation station = _fakers.TelevisionStation.GenerateOne(); + station.Broadcasts = _fakers.TelevisionBroadcast.GenerateSet(2); station.Broadcasts.ElementAt(1).ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -154,20 +154,20 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(station.StringId); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Id.Should().Be(station.Broadcasts.ElementAt(1).StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("archivedAt").With(value => value.Should().BeNull()); + responseDocument.Included[0].Attributes.Should().ContainKey("archivedAt").WhoseValue.Should().BeNull(); } [Fact] public async Task Get_primary_resource_by_ID_with_include_and_filter_includes_archived() { // Arrange - TelevisionStation station = _fakers.TelevisionStation.Generate(); - station.Broadcasts = _fakers.TelevisionBroadcast.Generate(2).ToHashSet(); + TelevisionStation station = _fakers.TelevisionStation.GenerateOne(); + station.Broadcasts = _fakers.TelevisionBroadcast.GenerateSet(2); station.Broadcasts.ElementAt(1).ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -184,22 +184,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(station.StringId); - responseDocument.Included.ShouldHaveCount(2); + responseDocument.Included.Should().HaveCount(2); responseDocument.Included[0].Id.Should().Be(station.Broadcasts.ElementAt(0).StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("archivedAt").With(value => value.Should().Be(station.Broadcasts.ElementAt(0).ArchivedAt)); + responseDocument.Included[0].Attributes.Should().ContainKey("archivedAt").WhoseValue.Should().Be(station.Broadcasts.ElementAt(0).ArchivedAt); responseDocument.Included[1].Id.Should().Be(station.Broadcasts.ElementAt(1).StringId); - responseDocument.Included[1].Attributes.ShouldContainKey("archivedAt").With(value => value.Should().BeNull()); + responseDocument.Included[1].Attributes.Should().ContainKey("archivedAt").WhoseValue.Should().BeNull(); } [Fact] public async Task Get_secondary_resource_includes_archived() { // Arrange - BroadcastComment comment = _fakers.BroadcastComment.Generate(); - comment.AppliesTo = _fakers.TelevisionBroadcast.Generate(); + BroadcastComment comment = _fakers.BroadcastComment.GenerateOne(); + comment.AppliesTo = _fakers.TelevisionBroadcast.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -215,17 +215,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(comment.AppliesTo.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("archivedAt").With(value => value.Should().Be(comment.AppliesTo.ArchivedAt)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("archivedAt").WhoseValue.Should().Be(comment.AppliesTo.ArchivedAt); } [Fact] public async Task Get_secondary_resources_excludes_archived() { // Arrange - TelevisionStation station = _fakers.TelevisionStation.Generate(); - station.Broadcasts = _fakers.TelevisionBroadcast.Generate(2).ToHashSet(); + TelevisionStation station = _fakers.TelevisionStation.GenerateOne(); + station.Broadcasts = _fakers.TelevisionBroadcast.GenerateSet(2); station.Broadcasts.ElementAt(1).ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -242,17 +242,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(station.Broadcasts.ElementAt(1).StringId); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("archivedAt").With(value => value.Should().BeNull()); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("archivedAt").WhoseValue.Should().BeNull(); } [Fact] public async Task Get_secondary_resources_with_filter_includes_archived() { // Arrange - TelevisionStation station = _fakers.TelevisionStation.Generate(); - station.Broadcasts = _fakers.TelevisionBroadcast.Generate(2).ToHashSet(); + TelevisionStation station = _fakers.TelevisionStation.GenerateOne(); + station.Broadcasts = _fakers.TelevisionBroadcast.GenerateSet(2); station.Broadcasts.ElementAt(1).ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -271,21 +271,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => DateTimeOffset archivedAt0 = station.Broadcasts.ElementAt(0).ArchivedAt!.Value; - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue[0].Id.Should().Be(station.Broadcasts.ElementAt(0).StringId); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("archivedAt").With(value => value.Should().Be(archivedAt0)); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("archivedAt").WhoseValue.Should().Be(archivedAt0); responseDocument.Data.ManyValue[1].Id.Should().Be(station.Broadcasts.ElementAt(1).StringId); - responseDocument.Data.ManyValue[1].Attributes.ShouldContainKey("archivedAt").With(value => value.Should().BeNull()); + responseDocument.Data.ManyValue[1].Attributes.Should().ContainKey("archivedAt").WhoseValue.Should().BeNull(); } [Fact] public async Task Get_secondary_resource_by_ID_with_include_excludes_archived() { // Arrange - TelevisionNetwork network = _fakers.TelevisionNetwork.Generate(); - network.Stations = _fakers.TelevisionStation.Generate(1).ToHashSet(); - network.Stations.ElementAt(0).Broadcasts = _fakers.TelevisionBroadcast.Generate(2).ToHashSet(); + TelevisionNetwork network = _fakers.TelevisionNetwork.GenerateOne(); + network.Stations = _fakers.TelevisionStation.GenerateSet(1); + network.Stations.ElementAt(0).Broadcasts = _fakers.TelevisionBroadcast.GenerateSet(2); network.Stations.ElementAt(0).Broadcasts.ElementAt(1).ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -302,20 +302,20 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(network.Stations.ElementAt(0).StringId); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Id.Should().Be(network.Stations.ElementAt(0).Broadcasts.ElementAt(1).StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("archivedAt").With(value => value.Should().BeNull()); + responseDocument.Included[0].Attributes.Should().ContainKey("archivedAt").WhoseValue.Should().BeNull(); } [Fact] public async Task Get_secondary_resource_by_ID_with_include_and_filter_includes_archived() { - TelevisionNetwork network = _fakers.TelevisionNetwork.Generate(); - network.Stations = _fakers.TelevisionStation.Generate(1).ToHashSet(); - network.Stations.ElementAt(0).Broadcasts = _fakers.TelevisionBroadcast.Generate(2).ToHashSet(); + TelevisionNetwork network = _fakers.TelevisionNetwork.GenerateOne(); + network.Stations = _fakers.TelevisionStation.GenerateSet(1); + network.Stations.ElementAt(0).Broadcasts = _fakers.TelevisionBroadcast.GenerateSet(2); network.Stations.ElementAt(0).Broadcasts.ElementAt(1).ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -335,22 +335,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => DateTimeOffset archivedAt0 = network.Stations.ElementAt(0).Broadcasts.ElementAt(0).ArchivedAt!.Value; - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(network.Stations.ElementAt(0).StringId); - responseDocument.Included.ShouldHaveCount(2); + responseDocument.Included.Should().HaveCount(2); responseDocument.Included[0].Id.Should().Be(network.Stations.ElementAt(0).Broadcasts.ElementAt(0).StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("archivedAt").With(value => value.Should().Be(archivedAt0)); + responseDocument.Included[0].Attributes.Should().ContainKey("archivedAt").WhoseValue.Should().Be(archivedAt0); responseDocument.Included[1].Id.Should().Be(network.Stations.ElementAt(0).Broadcasts.ElementAt(1).StringId); - responseDocument.Included[1].Attributes.ShouldContainKey("archivedAt").With(value => value.Should().BeNull()); + responseDocument.Included[1].Attributes.Should().ContainKey("archivedAt").WhoseValue.Should().BeNull(); } [Fact] public async Task Get_ToMany_relationship_excludes_archived() { // Arrange - TelevisionStation station = _fakers.TelevisionStation.Generate(); - station.Broadcasts = _fakers.TelevisionBroadcast.Generate(2).ToHashSet(); + TelevisionStation station = _fakers.TelevisionStation.GenerateOne(); + station.Broadcasts = _fakers.TelevisionBroadcast.GenerateSet(2); station.Broadcasts.ElementAt(1).ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -367,7 +367,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(station.Broadcasts.ElementAt(1).StringId); } @@ -375,8 +375,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_ToMany_relationship_with_filter_includes_archived() { // Arrange - TelevisionStation station = _fakers.TelevisionStation.Generate(); - station.Broadcasts = _fakers.TelevisionBroadcast.Generate(2).ToHashSet(); + TelevisionStation station = _fakers.TelevisionStation.GenerateOne(); + station.Broadcasts = _fakers.TelevisionBroadcast.GenerateSet(2); station.Broadcasts.ElementAt(1).ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -393,7 +393,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue[0].Id.Should().Be(station.Broadcasts.ElementAt(0).StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(station.Broadcasts.ElementAt(1).StringId); } @@ -402,7 +402,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_unarchived_resource() { // Arrange - TelevisionBroadcast newBroadcast = _fakers.TelevisionBroadcast.Generate(); + TelevisionBroadcast newBroadcast = _fakers.TelevisionBroadcast.GenerateOne(); var requestBody = new { @@ -425,17 +425,17 @@ public async Task Can_create_unarchived_resource() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("title").With(value => value.Should().Be(newBroadcast.Title)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("airedAt").With(value => value.Should().Be(newBroadcast.AiredAt)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("archivedAt").With(value => value.Should().BeNull()); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(newBroadcast.Title); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("airedAt").WhoseValue.Should().Be(newBroadcast.AiredAt); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("archivedAt").WhoseValue.Should().BeNull(); } [Fact] public async Task Cannot_create_archived_resource() { // Arrange - TelevisionBroadcast newBroadcast = _fakers.TelevisionBroadcast.Generate(); + TelevisionBroadcast newBroadcast = _fakers.TelevisionBroadcast.GenerateOne(); var requestBody = new { @@ -459,7 +459,7 @@ public async Task Cannot_create_archived_resource() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); @@ -471,10 +471,10 @@ public async Task Cannot_create_archived_resource() public async Task Can_archive_resource() { // Arrange - TelevisionBroadcast existingBroadcast = _fakers.TelevisionBroadcast.Generate(); + TelevisionBroadcast existingBroadcast = _fakers.TelevisionBroadcast.GenerateOne(); existingBroadcast.ArchivedAt = null; - DateTimeOffset newArchivedAt = _fakers.TelevisionBroadcast.Generate().ArchivedAt!.Value; + DateTimeOffset newArchivedAt = _fakers.TelevisionBroadcast.GenerateOne().ArchivedAt!.Value; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -517,7 +517,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_unarchive_resource() { // Arrange - TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.Generate(); + TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -560,9 +560,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_shift_archive_date() { // Arrange - TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.Generate(); + TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.GenerateOne(); - DateTimeOffset? newArchivedAt = _fakers.TelevisionBroadcast.Generate().ArchivedAt; + DateTimeOffset? newArchivedAt = _fakers.TelevisionBroadcast.GenerateOne().ArchivedAt; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -591,7 +591,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); @@ -603,7 +603,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_archived_resource() { // Arrange - TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.Generate(); + TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -633,7 +633,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_delete_unarchived_resource() { // Arrange - TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.Generate(); + TelevisionBroadcast broadcast = _fakers.TelevisionBroadcast.GenerateOne(); broadcast.ArchivedAt = null; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -650,7 +650,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Archiving/TelevisionDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Archiving/TelevisionDbContext.cs index b05a82f382..fe83dace37 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Archiving/TelevisionDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Archiving/TelevisionDbContext.cs @@ -5,7 +5,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.Archiving; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class TelevisionDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class TelevisionDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet Networks => Set(); public DbSet Stations => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Controllers/AtomicCustomConstrainedOperationsControllerTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Controllers/AtomicCustomConstrainedOperationsControllerTests.cs index 099168b124..b515ff7c13 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Controllers/AtomicCustomConstrainedOperationsControllerTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Controllers/AtomicCustomConstrainedOperationsControllerTests.cs @@ -23,8 +23,8 @@ public AtomicCustomConstrainedOperationsControllerTests(IntegrationTestContext { @@ -147,13 +147,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); error.Title.Should().Be("The requested operation is not accessible."); error.Detail.Should().Be("The 'update' resource operation is not accessible for resource type 'musicTracks'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); } @@ -161,8 +161,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_to_ToMany_relationship_for_inaccessible_operation() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - Performer existingPerformer = _fakers.Performer.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + Performer existingPerformer = _fakers.Performer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -203,13 +203,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); error.Title.Should().Be("The requested operation is not accessible."); error.Detail.Should().Be("The 'add' relationship operation is not accessible for relationship 'performers' on resource type 'musicTracks'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Controllers/AtomicDefaultConstrainedOperationsControllerTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Controllers/AtomicDefaultConstrainedOperationsControllerTests.cs index caffc32e2b..bec1bdc883 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Controllers/AtomicDefaultConstrainedOperationsControllerTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Controllers/AtomicDefaultConstrainedOperationsControllerTests.cs @@ -23,7 +23,7 @@ public AtomicDefaultConstrainedOperationsControllerTests(IntegrationTestContext< public async Task Cannot_delete_resource_for_inaccessible_operation() { // Arrange - TextLanguage existingLanguage = _fakers.TextLanguage.Generate(); + TextLanguage existingLanguage = _fakers.TextLanguage.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -55,13 +55,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); error.Title.Should().Be("The requested operation is not accessible."); error.Detail.Should().Be("The 'remove' resource operation is not accessible for resource type 'textLanguages'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); } @@ -69,8 +69,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_change_ToMany_relationship_for_inaccessible_operations() { // Arrange - TextLanguage existingLanguage = _fakers.TextLanguage.Generate(); - Lyric existingLyric = _fakers.Lyric.Generate(); + TextLanguage existingLanguage = _fakers.TextLanguage.GenerateOne(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -147,27 +147,27 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(3); + responseDocument.Errors.Should().HaveCount(3); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.Forbidden); error1.Title.Should().Be("The requested operation is not accessible."); error1.Detail.Should().Be("The 'update' relationship operation is not accessible for relationship 'lyrics' on resource type 'textLanguages'."); - error1.Source.ShouldNotBeNull(); + error1.Source.Should().NotBeNull(); error1.Source.Pointer.Should().Be("/atomic:operations[0]"); ErrorObject error2 = responseDocument.Errors[1]; error2.StatusCode.Should().Be(HttpStatusCode.Forbidden); error2.Title.Should().Be("The requested operation is not accessible."); error2.Detail.Should().Be("The 'add' relationship operation is not accessible for relationship 'lyrics' on resource type 'textLanguages'."); - error2.Source.ShouldNotBeNull(); + error2.Source.Should().NotBeNull(); error2.Source.Pointer.Should().Be("/atomic:operations[1]"); ErrorObject error3 = responseDocument.Errors[2]; error3.StatusCode.Should().Be(HttpStatusCode.Forbidden); error3.Title.Should().Be("The requested operation is not accessible."); error3.Detail.Should().Be("The 'remove' relationship operation is not accessible for relationship 'lyrics' on resource type 'textLanguages'."); - error3.Source.ShouldNotBeNull(); + error3.Source.Should().NotBeNull(); error3.Source.Pointer.Should().Be("/atomic:operations[2]"); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Controllers/CreateMusicTrackOperationsController.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Controllers/CreateMusicTrackOperationsController.cs index b3f98df0bc..81efcf9b1d 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Controllers/CreateMusicTrackOperationsController.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Controllers/CreateMusicTrackOperationsController.cs @@ -13,8 +13,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.AtomicOperations.Controllers; [Route("/operations/musicTracks/create")] public sealed class CreateMusicTrackOperationsController( IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, IOperationsProcessor processor, IJsonApiRequest request, - ITargetedFields targetedFields) : JsonApiOperationsController(options, resourceGraph, loggerFactory, processor, request, targetedFields, - OnlyCreateMusicTracksOperationFilter.Instance) + ITargetedFields targetedFields) + : JsonApiOperationsController(options, resourceGraph, loggerFactory, processor, request, targetedFields, OnlyCreateMusicTracksOperationFilter.Instance) { private sealed class OnlyCreateMusicTracksOperationFilter : IAtomicOperationFilter { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AssignIdToTextLanguageDefinition.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AssignIdToTextLanguageDefinition.cs new file mode 100644 index 0000000000..730f255af9 --- /dev/null +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AssignIdToTextLanguageDefinition.cs @@ -0,0 +1,20 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Middleware; + +namespace JsonApiDotNetCoreTests.IntegrationTests.AtomicOperations.Creating; + +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +public sealed class AssignIdToTextLanguageDefinition(IResourceGraph resourceGraph, ResourceDefinitionHitCounter hitCounter, OperationsDbContext dbContext) + : ImplicitlyChangingTextLanguageDefinition(resourceGraph, hitCounter, dbContext) +{ + public override Task OnWritingAsync(TextLanguage resource, WriteOperationKind writeOperation, CancellationToken cancellationToken) + { + if (writeOperation == WriteOperationKind.CreateResource && resource.Id == Guid.Empty) + { + resource.Id = Guid.NewGuid(); + } + + return Task.CompletedTask; + } +} diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceTests.cs index c77610d8dc..8b0090fe8e 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceTests.cs @@ -26,8 +26,6 @@ public AtomicCreateResourceTests(IntegrationTestContext(); testContext.UseController(); - testContext.ConfigureServices(services => services.AddSingleton()); - var options = (JsonApiOptions)testContext.Factory.Services.GetRequiredService(); options.AllowUnknownFieldsInRequestBody = false; } @@ -36,8 +34,8 @@ public AtomicCreateResourceTests(IntegrationTestContext + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("performers"); - resource.Attributes.ShouldContainKey("artistName").With(value => value.Should().Be(newArtistName)); - resource.Attributes.ShouldContainKey("bornAt").With(value => value.Should().Be(newBornAt)); + resource.Attributes.Should().ContainKey("artistName").WhoseValue.Should().Be(newArtistName); + resource.Attributes.Should().ContainKey("bornAt").WhoseValue.Should().Be(newBornAt); resource.Relationships.Should().BeNull(); }); - int newPerformerId = int.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); + int newPerformerId = int.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -94,7 +92,7 @@ public async Task Can_create_resources() // Arrange const int elementCount = 5; - List newTracks = _fakers.MusicTrack.Generate(elementCount); + List newTracks = _fakers.MusicTrack.GenerateList(elementCount); var operationElements = new List(elementCount); @@ -130,33 +128,30 @@ public async Task Can_create_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(elementCount); + responseDocument.Results.Should().HaveCount(elementCount); for (int index = 0; index < elementCount; index++) { - responseDocument.Results[index].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[index].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { - resource.ShouldNotBeNull(); + resource.Should().NotBeNull(); resource.Type.Should().Be("musicTracks"); - resource.Attributes.ShouldContainKey("title").With(value => value.Should().Be(newTracks[index].Title)); - - resource.Attributes.ShouldContainKey("lengthInSeconds") - .With(value => value.As().Should().BeApproximately(newTracks[index].LengthInSeconds)); - - resource.Attributes.ShouldContainKey("genre").With(value => value.Should().Be(newTracks[index].Genre)); - resource.Attributes.ShouldContainKey("releasedAt").With(value => value.Should().Be(newTracks[index].ReleasedAt)); + resource.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(newTracks[index].Title); + resource.Attributes.Should().ContainKey("lengthInSeconds").WhoseValue.As().Should().BeApproximately(newTracks[index].LengthInSeconds); + resource.Attributes.Should().ContainKey("genre").WhoseValue.Should().Be(newTracks[index].Genre); + resource.Attributes.Should().ContainKey("releasedAt").WhoseValue.Should().Be(newTracks[index].ReleasedAt); - resource.Relationships.ShouldNotBeEmpty(); + resource.Relationships.Should().NotBeEmpty(); }); } - Guid[] newTrackIds = responseDocument.Results.Select(result => Guid.Parse(result.Data.SingleValue!.Id.ShouldNotBeNull())).ToArray(); + Guid[] newTrackIds = responseDocument.Results.Select(result => Guid.Parse(result.Data.SingleValue!.Id.Should().NotBeNull().And.Subject)).ToArray(); await _testContext.RunOnDatabaseAsync(async dbContext => { List tracksInDatabase = await dbContext.MusicTracks.Where(musicTrack => newTrackIds.Contains(musicTrack.Id)).ToListAsync(); - tracksInDatabase.ShouldHaveCount(elementCount); + tracksInDatabase.Should().HaveCount(elementCount); for (int index = 0; index < elementCount; index++) { @@ -203,17 +198,17 @@ public async Task Can_create_resource_without_attributes_or_relationships() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(1); + responseDocument.Results.Should().HaveCount(1); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("performers"); - resource.Attributes.ShouldContainKey("artistName").With(value => value.Should().BeNull()); - resource.Attributes.ShouldContainKey("bornAt").With(value => value.Should().Be(default(DateTimeOffset))); + resource.Attributes.Should().ContainKey("artistName").WhoseValue.Should().BeNull(); + resource.Attributes.Should().ContainKey("bornAt").WhoseValue.Should().Be(default(DateTimeOffset)); resource.Relationships.Should().BeNull(); }); - int newPerformerId = int.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); + int newPerformerId = int.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -228,7 +223,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_resource_with_unknown_attribute() { // Arrange - string newName = _fakers.Playlist.Generate().Name; + string newName = _fakers.Playlist.GenerateOne().Name; var requestBody = new { @@ -258,15 +253,15 @@ public async Task Cannot_create_resource_with_unknown_attribute() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown attribute found."); error.Detail.Should().Be("Attribute 'doesNotExist' does not exist on resource type 'playlists'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/attributes/doesNotExist"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -276,7 +271,7 @@ public async Task Can_create_resource_with_unknown_attribute() var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.AllowUnknownFieldsInRequestBody = true; - string newName = _fakers.Playlist.Generate().Name; + string newName = _fakers.Playlist.GenerateOne().Name; var requestBody = new { @@ -306,16 +301,16 @@ public async Task Can_create_resource_with_unknown_attribute() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(1); + responseDocument.Results.Should().HaveCount(1); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("playlists"); - resource.Attributes.ShouldContainKey("name").With(value => value.Should().Be(newName)); - resource.Relationships.ShouldNotBeEmpty(); + resource.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(newName); + resource.Relationships.Should().NotBeEmpty(); }); - long newPlaylistId = long.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); + long newPlaylistId = long.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -363,15 +358,15 @@ public async Task Cannot_create_resource_with_unknown_relationship() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown relationship found."); error.Detail.Should().Be("Relationship 'doesNotExist' does not exist on resource type 'lyrics'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/doesNotExist"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -381,7 +376,7 @@ public async Task Can_create_resource_with_unknown_relationship() var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.AllowUnknownFieldsInRequestBody = true; - string newLyricText = _fakers.Lyric.Generate().Text; + string newLyricText = _fakers.Lyric.GenerateOne().Text; var requestBody = new { @@ -421,22 +416,22 @@ public async Task Can_create_resource_with_unknown_relationship() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(1); + responseDocument.Results.Should().HaveCount(1); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("lyrics"); - resource.Attributes.ShouldNotBeEmpty(); - resource.Relationships.ShouldNotBeEmpty(); + resource.Attributes.Should().NotBeEmpty(); + resource.Relationships.Should().NotBeEmpty(); }); - long newLyricId = long.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); + long newLyricId = long.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { Lyric lyricInDatabase = await dbContext.Lyrics.FirstWithIdAsync(newLyricId); - lyricInDatabase.ShouldNotBeNull(); + lyricInDatabase.Should().NotBeNull(); }); } @@ -444,7 +439,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_resource_with_client_generated_ID() { // Arrange - MusicTrack newTrack = _fakers.MusicTrack.Generate(); + MusicTrack newTrack = _fakers.MusicTrack.GenerateOne(); newTrack.Id = Guid.NewGuid(); var requestBody = new @@ -475,15 +470,15 @@ public async Task Cannot_create_resource_with_client_generated_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); error.Title.Should().Be("Failed to deserialize request body: The use of client-generated IDs is disabled."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/id"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -510,15 +505,15 @@ public async Task Cannot_create_resource_for_href_element() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'href' element is not supported."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/href"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -548,15 +543,15 @@ public async Task Cannot_create_resource_for_ref_element() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'relationship' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -582,15 +577,15 @@ public async Task Cannot_create_resource_for_missing_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'data' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -617,22 +612,22 @@ public async Task Cannot_create_resource_for_null_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object, instead of 'null'."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_resource_for_array_data() { // Arrange - string newArtistName = _fakers.Performer.Generate().ArtistName!; + string newArtistName = _fakers.Performer.GenerateOne().ArtistName!; var requestBody = new { @@ -664,15 +659,15 @@ public async Task Cannot_create_resource_for_array_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object, instead of an array."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -704,15 +699,15 @@ public async Task Cannot_create_resource_for_missing_type() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -742,22 +737,22 @@ public async Task Cannot_create_resource_for_unknown_type() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_resource_with_readonly_attribute() { // Arrange - string newPlaylistName = _fakers.Playlist.Generate().Name; + string newPlaylistName = _fakers.Playlist.GenerateOne().Name; var requestBody = new { @@ -787,15 +782,15 @@ public async Task Cannot_create_resource_with_readonly_attribute() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Attribute is read-only."); error.Detail.Should().Be("Attribute 'isArchived' on resource type 'playlists' is read-only."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/attributes/isArchived"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -829,26 +824,26 @@ public async Task Cannot_create_resource_with_incompatible_attribute_value() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Incompatible attribute value found."); error.Detail.Should().Be("Failed to convert attribute 'bornAt' with value '12345' of type 'Number' to type 'DateTimeOffset'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/attributes/bornAt"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_create_resource_with_attributes_and_multiple_relationship_types() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); - Performer existingPerformer = _fakers.Performer.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); + Performer existingPerformer = _fakers.Performer.GenerateOne(); - string newTitle = _fakers.MusicTrack.Generate().Title; + string newTitle = _fakers.MusicTrack.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -913,16 +908,16 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(1); + responseDocument.Results.Should().HaveCount(1); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("musicTracks"); - resource.Attributes.ShouldContainKey("title").With(value => value.Should().Be(newTitle)); - resource.Relationships.ShouldNotBeEmpty(); + resource.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(newTitle); + resource.Relationships.Should().NotBeEmpty(); }); - Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); + Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -940,13 +935,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => trackInDatabase.Title.Should().Be(newTitle); - trackInDatabase.Lyric.ShouldNotBeNull(); + trackInDatabase.Lyric.Should().NotBeNull(); trackInDatabase.Lyric.Id.Should().Be(existingLyric.Id); - trackInDatabase.OwnedBy.ShouldNotBeNull(); + trackInDatabase.OwnedBy.Should().NotBeNull(); trackInDatabase.OwnedBy.Id.Should().Be(existingCompany.Id); - trackInDatabase.Performers.ShouldHaveCount(1); + trackInDatabase.Performers.Should().HaveCount(1); trackInDatabase.Performers[0].Id.Should().Be(existingPerformer.Id); }); } @@ -982,14 +977,14 @@ public async Task Cannot_assign_attribute_with_blocked_capability() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Attribute value cannot be assigned when creating resource."); error.Detail.Should().Be("The attribute 'createdAt' on resource type 'lyrics' cannot be assigned to."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/attributes/createdAt"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithClientGeneratedIdTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithClientGeneratedIdTests.cs index e69cfb7d1a..0d8f7b14a7 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithClientGeneratedIdTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithClientGeneratedIdTests.cs @@ -25,21 +25,22 @@ public AtomicCreateResourceWithClientGeneratedIdTests(IntegrationTestContext { - services.AddResourceDefinition(); + services.AddResourceDefinition(); services.AddSingleton(); - services.AddSingleton(); }); - - var options = (JsonApiOptions)testContext.Factory.Services.GetRequiredService(); - options.ClientIdGeneration = ClientIdGenerationMode.Required; } - [Fact] - public async Task Can_create_resource_with_client_generated_guid_ID_having_side_effects() + [Theory] + [InlineData(ClientIdGenerationMode.Allowed)] + [InlineData(ClientIdGenerationMode.Required)] + public async Task Can_create_resource_with_client_generated_guid_ID_having_side_effects(ClientIdGenerationMode mode) { // Arrange - TextLanguage newLanguage = _fakers.TextLanguage.Generate(); + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.ClientIdGeneration = mode; + + TextLanguage newLanguage = _fakers.TextLanguage.GenerateOne(); newLanguage.Id = Guid.NewGuid(); var requestBody = new @@ -72,14 +73,14 @@ public async Task Can_create_resource_with_client_generated_guid_ID_having_side_ string isoCode = $"{newLanguage.IsoCode}{ImplicitlyChangingTextLanguageDefinition.Suffix}"; - responseDocument.Results.ShouldHaveCount(1); + responseDocument.Results.Should().HaveCount(1); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("textLanguages"); - resource.Attributes.ShouldContainKey("isoCode").With(value => value.Should().Be(isoCode)); + resource.Attributes.Should().ContainKey("isoCode").WhoseValue.Should().Be(isoCode); resource.Attributes.Should().NotContainKey("isRightToLeft"); - resource.Relationships.ShouldNotBeEmpty(); + resource.Relationships.Should().NotBeEmpty(); }); await _testContext.RunOnDatabaseAsync(async dbContext => @@ -90,11 +91,16 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }); } - [Fact] - public async Task Can_create_resource_with_client_generated_string_ID_having_no_side_effects() + [Theory] + [InlineData(ClientIdGenerationMode.Allowed)] + [InlineData(ClientIdGenerationMode.Required)] + public async Task Can_create_resource_with_client_generated_guid_ID_having_no_side_effects(ClientIdGenerationMode mode) { // Arrange - MusicTrack newTrack = _fakers.MusicTrack.Generate(); + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.ClientIdGeneration = mode; + + MusicTrack newTrack = _fakers.MusicTrack.GenerateOne(); newTrack.Id = Guid.NewGuid(); var requestBody = new @@ -138,11 +144,73 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }); } - [Fact] - public async Task Cannot_create_resource_for_missing_client_generated_ID() + [Theory] + [InlineData(ClientIdGenerationMode.Allowed)] + public async Task Can_create_resource_for_missing_client_generated_ID_having_side_effects(ClientIdGenerationMode mode) + { + // Arrange + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.ClientIdGeneration = mode; + + string? newIsoCode = _fakers.TextLanguage.GenerateOne().IsoCode; + + var requestBody = new + { + atomic__operations = new[] + { + new + { + op = "add", + data = new + { + type = "textLanguages", + attributes = new + { + isoCode = newIsoCode + } + } + } + } + }; + + const string route = "/operations"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAtomicAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); + + string isoCode = $"{newIsoCode}{ImplicitlyChangingTextLanguageDefinition.Suffix}"; + + responseDocument.Results.Should().HaveCount(1); + + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => + { + resource.Type.Should().Be("textLanguages"); + resource.Attributes.Should().ContainKey("isoCode").WhoseValue.Should().Be(isoCode); + resource.Relationships.Should().NotBeEmpty(); + }); + + Guid newLanguageId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + TextLanguage languageInDatabase = await dbContext.TextLanguages.FirstWithIdAsync(newLanguageId); + + languageInDatabase.IsoCode.Should().Be(isoCode); + }); + } + + [Theory] + [InlineData(ClientIdGenerationMode.Required)] + public async Task Cannot_create_resource_for_missing_client_generated_ID(ClientIdGenerationMode mode) { // Arrange - string? newIsoCode = _fakers.TextLanguage.Generate().IsoCode; + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.ClientIdGeneration = mode; + + string? newIsoCode = _fakers.TextLanguage.GenerateOne().IsoCode; var requestBody = new { @@ -171,25 +239,30 @@ public async Task Cannot_create_resource_for_missing_client_generated_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } - [Fact] - public async Task Cannot_create_resource_for_existing_client_generated_ID() + [Theory] + [InlineData(ClientIdGenerationMode.Allowed)] + [InlineData(ClientIdGenerationMode.Required)] + public async Task Cannot_create_resource_for_existing_client_generated_ID(ClientIdGenerationMode mode) { // Arrange - TextLanguage existingLanguage = _fakers.TextLanguage.Generate(); + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.ClientIdGeneration = mode; + + TextLanguage existingLanguage = _fakers.TextLanguage.GenerateOne(); existingLanguage.Id = Guid.NewGuid(); - TextLanguage languageToCreate = _fakers.TextLanguage.Generate(); + TextLanguage languageToCreate = _fakers.TextLanguage.GenerateOne(); languageToCreate.Id = existingLanguage.Id; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -226,21 +299,26 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Another resource with the specified ID already exists."); error.Detail.Should().Be($"Another resource of type 'textLanguages' with ID '{languageToCreate.StringId}' already exists."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); error.Meta.Should().NotContainKey("requestBody"); } - [Fact] - public async Task Cannot_create_resource_for_incompatible_ID() + [Theory] + [InlineData(ClientIdGenerationMode.Allowed)] + [InlineData(ClientIdGenerationMode.Required)] + public async Task Cannot_create_resource_for_incompatible_ID(ClientIdGenerationMode mode) { // Arrange + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.ClientIdGeneration = mode; + string guid = Unknown.StringId.Guid; var requestBody = new @@ -270,21 +348,82 @@ public async Task Cannot_create_resource_for_incompatible_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Incompatible 'id' value found."); error.Detail.Should().Be($"Failed to convert '{guid}' of type 'String' to type 'Int32'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/id"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } - [Fact] - public async Task Cannot_create_resource_with_local_ID() + [Theory] + [InlineData(ClientIdGenerationMode.Allowed)] + public async Task Can_create_resource_with_local_ID(ClientIdGenerationMode mode) { // Arrange + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.ClientIdGeneration = mode; + + string newTitle = _fakers.MusicTrack.GenerateOne().Title; + + var requestBody = new + { + atomic__operations = new[] + { + new + { + op = "add", + data = new + { + type = "musicTracks", + lid = "new-server-id", + attributes = new + { + title = newTitle + } + } + } + } + }; + + const string route = "/operations"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAtomicAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); + + responseDocument.Results.Should().HaveCount(1); + + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => + { + resource.Type.Should().Be("musicTracks"); + resource.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(newTitle); + resource.Relationships.Should().BeNull(); + }); + + Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + MusicTrack languageInDatabase = await dbContext.MusicTracks.FirstWithIdAsync(newTrackId); + + languageInDatabase.Title.Should().Be(newTitle); + }); + } + + [Theory] + [InlineData(ClientIdGenerationMode.Required)] + public async Task Cannot_create_resource_with_local_ID(ClientIdGenerationMode mode) + { + // Arrange + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.ClientIdGeneration = mode; + var requestBody = new { atomic__operations = new[] @@ -309,21 +448,26 @@ public async Task Cannot_create_resource_with_local_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'lid' element cannot be used because a client-generated ID is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/lid"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } - [Fact] - public async Task Cannot_create_resource_for_ID_and_local_ID() + [Theory] + [InlineData(ClientIdGenerationMode.Allowed)] + [InlineData(ClientIdGenerationMode.Required)] + public async Task Cannot_create_resource_for_ID_and_local_ID(ClientIdGenerationMode mode) { // Arrange + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.ClientIdGeneration = mode; + var requestBody = new { atomic__operations = new[] @@ -349,14 +493,14 @@ public async Task Cannot_create_resource_for_ID_and_local_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' and 'lid' element are mutually exclusive."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToManyRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToManyRelationshipTests.cs index 61a1db5164..0b86e91ddf 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToManyRelationshipTests.cs @@ -28,8 +28,8 @@ public AtomicCreateResourceWithToManyRelationshipTests(IntegrationTestContext existingPerformers = _fakers.Performer.Generate(2); - string newTitle = _fakers.MusicTrack.Generate().Title; + List existingPerformers = _fakers.Performer.GenerateList(2); + string newTitle = _fakers.MusicTrack.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -83,22 +83,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(1); + responseDocument.Results.Should().HaveCount(1); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("musicTracks"); - resource.Attributes.ShouldNotBeEmpty(); - resource.Relationships.ShouldNotBeEmpty(); + resource.Attributes.Should().NotBeEmpty(); + resource.Relationships.Should().NotBeEmpty(); }); - Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); + Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { MusicTrack trackInDatabase = await dbContext.MusicTracks.Include(musicTrack => musicTrack.Performers).FirstWithIdAsync(newTrackId); - trackInDatabase.Performers.ShouldHaveCount(2); + trackInDatabase.Performers.Should().HaveCount(2); trackInDatabase.Performers.Should().ContainSingle(performer => performer.Id == existingPerformers[0].Id); trackInDatabase.Performers.Should().ContainSingle(performer => performer.Id == existingPerformers[1].Id); }); @@ -108,8 +108,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_ManyToMany_relationship() { // Arrange - List existingTracks = _fakers.MusicTrack.Generate(3); - string newName = _fakers.Playlist.Generate().Name; + List existingTracks = _fakers.MusicTrack.GenerateList(3); + string newName = _fakers.Playlist.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -168,22 +168,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(1); + responseDocument.Results.Should().HaveCount(1); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("playlists"); - resource.Attributes.ShouldNotBeEmpty(); - resource.Relationships.ShouldNotBeEmpty(); + resource.Attributes.Should().NotBeEmpty(); + resource.Relationships.Should().NotBeEmpty(); }); - long newPlaylistId = long.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); + long newPlaylistId = long.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { Playlist playlistInDatabase = await dbContext.Playlists.Include(playlist => playlist.Tracks).FirstWithIdAsync(newPlaylistId); - playlistInDatabase.Tracks.ShouldHaveCount(3); + playlistInDatabase.Tracks.Should().HaveCount(3); playlistInDatabase.Tracks.Should().ContainSingle(musicTrack => musicTrack.Id == existingTracks[0].Id); playlistInDatabase.Tracks.Should().ContainSingle(musicTrack => musicTrack.Id == existingTracks[1].Id); playlistInDatabase.Tracks.Should().ContainSingle(musicTrack => musicTrack.Id == existingTracks[2].Id); @@ -230,15 +230,15 @@ public async Task Cannot_create_for_missing_relationship_type() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/performers/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -282,15 +282,15 @@ public async Task Cannot_create_for_unknown_relationship_type() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/performers/data[0]/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -333,22 +333,22 @@ public async Task Cannot_create_for_missing_relationship_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' or 'lid' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/performers/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_for_unknown_relationship_IDs() { // Arrange - string newTitle = _fakers.MusicTrack.Generate().Title; + string newTitle = _fakers.MusicTrack.GenerateOne().Title; string performerId1 = Unknown.StringId.For(); string performerId2 = Unknown.StringId.AltFor(); @@ -399,13 +399,13 @@ public async Task Cannot_create_for_unknown_relationship_IDs() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(2); + responseDocument.Errors.Should().HaveCount(2); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.NotFound); error1.Title.Should().Be("A related resource does not exist."); error1.Detail.Should().Be($"Related resource of type 'performers' with ID '{performerId1}' in relationship 'performers' does not exist."); - error1.Source.ShouldNotBeNull(); + error1.Source.Should().NotBeNull(); error1.Source.Pointer.Should().Be("/atomic:operations[0]"); error1.Meta.Should().NotContainKey("requestBody"); @@ -413,7 +413,7 @@ public async Task Cannot_create_for_unknown_relationship_IDs() error2.StatusCode.Should().Be(HttpStatusCode.NotFound); error2.Title.Should().Be("A related resource does not exist."); error2.Detail.Should().Be($"Related resource of type 'performers' with ID '{performerId2}' in relationship 'performers' does not exist."); - error2.Source.ShouldNotBeNull(); + error2.Source.Should().NotBeNull(); error2.Source.Pointer.Should().Be("/atomic:operations[0]"); error2.Meta.Should().NotContainKey("requestBody"); } @@ -459,23 +459,23 @@ public async Task Cannot_create_on_relationship_type_mismatch() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Incompatible resource type found."); error.Detail.Should().Be("Type 'playlists' is not convertible to type 'performers' of relationship 'performers'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/performers/data[0]/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_create_with_duplicates() { // Arrange - Performer existingPerformer = _fakers.Performer.Generate(); - string newTitle = _fakers.MusicTrack.Generate().Title; + Performer existingPerformer = _fakers.Performer.GenerateOne(); + string newTitle = _fakers.MusicTrack.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -529,22 +529,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(1); + responseDocument.Results.Should().HaveCount(1); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("musicTracks"); - resource.Attributes.ShouldNotBeEmpty(); - resource.Relationships.ShouldNotBeEmpty(); + resource.Attributes.Should().NotBeEmpty(); + resource.Relationships.Should().NotBeEmpty(); }); - Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); + Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { MusicTrack trackInDatabase = await dbContext.MusicTracks.Include(musicTrack => musicTrack.Performers).FirstWithIdAsync(newTrackId); - trackInDatabase.Performers.ShouldHaveCount(1); + trackInDatabase.Performers.Should().HaveCount(1); trackInDatabase.Performers[0].Id.Should().Be(existingPerformer.Id); }); } @@ -582,15 +582,15 @@ public async Task Cannot_create_with_missing_data_in_OneToMany_relationship() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'data' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/performers"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -627,15 +627,15 @@ public async Task Cannot_create_with_null_data_in_ManyToMany_relationship() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an array, instead of 'null'."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/tracks/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -674,15 +674,15 @@ public async Task Cannot_create_with_object_data_in_ManyToMany_relationship() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an array, instead of an object."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/tracks/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -726,14 +726,14 @@ public async Task Cannot_assign_relationship_with_blocked_capability() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Relationship cannot be assigned."); error.Detail.Should().Be("The relationship 'occursIn' on resource type 'musicTracks' cannot be assigned to."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/occursIn"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToOneRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToOneRelationshipTests.cs index 5d138404ba..a140a52322 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToOneRelationshipTests.cs @@ -29,9 +29,9 @@ public AtomicCreateResourceWithToOneRelationshipTests(IntegrationTestContext { @@ -77,22 +77,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(1); + responseDocument.Results.Should().HaveCount(1); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("lyrics"); - resource.Attributes.ShouldNotBeEmpty(); - resource.Relationships.ShouldNotBeEmpty(); + resource.Attributes.Should().NotBeEmpty(); + resource.Relationships.Should().NotBeEmpty(); }); - long newLyricId = long.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); + long newLyricId = long.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { Lyric lyricInDatabase = await dbContext.Lyrics.Include(lyric => lyric.Track).FirstWithIdAsync(newLyricId); - lyricInDatabase.Track.ShouldNotBeNull(); + lyricInDatabase.Track.Should().NotBeNull(); lyricInDatabase.Track.Id.Should().Be(existingTrack.Id); }); } @@ -101,8 +101,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToOne_relationship_from_dependent_side() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + Lyric existingLyric = _fakers.Lyric.GenerateOne(); + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -148,22 +148,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(1); + responseDocument.Results.Should().HaveCount(1); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("musicTracks"); - resource.Attributes.ShouldNotBeEmpty(); - resource.Relationships.ShouldNotBeEmpty(); + resource.Attributes.Should().NotBeEmpty(); + resource.Relationships.Should().NotBeEmpty(); }); - Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); + Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { MusicTrack trackInDatabase = await dbContext.MusicTracks.Include(musicTrack => musicTrack.Lyric).FirstWithIdAsync(newTrackId); - trackInDatabase.Lyric.ShouldNotBeNull(); + trackInDatabase.Lyric.Should().NotBeNull(); trackInDatabase.Lyric.Id.Should().Be(existingLyric.Id); }); } @@ -174,8 +174,8 @@ public async Task Can_create_resources_with_ToOne_relationship() // Arrange const int elementCount = 5; - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); - string[] newTrackTitles = _fakers.MusicTrack.Generate(elementCount).Select(musicTrack => musicTrack.Title).ToArray(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); + string[] newTrackTitles = _fakers.MusicTrack.GenerateList(elementCount).Select(musicTrack => musicTrack.Title).ToArray(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -225,18 +225,18 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(elementCount); + responseDocument.Results.Should().HaveCount(elementCount); for (int index = 0; index < elementCount; index++) { - responseDocument.Results[index].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[index].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("musicTracks"); - resource.Attributes.ShouldContainKey("title").With(value => value.Should().Be(newTrackTitles[index])); + resource.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(newTrackTitles[index]); }); } - Guid[] newTrackIds = responseDocument.Results.Select(result => Guid.Parse(result.Data.SingleValue!.Id.ShouldNotBeNull())).ToArray(); + Guid[] newTrackIds = responseDocument.Results.Select(result => Guid.Parse(result.Data.SingleValue!.Id.Should().NotBeNull().And.Subject)).ToArray(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -251,7 +251,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // @formatter:wrap_after_property_in_chained_method_calls restore // @formatter:wrap_chained_method_calls restore - tracksInDatabase.ShouldHaveCount(elementCount); + tracksInDatabase.Should().HaveCount(elementCount); for (int index = 0; index < elementCount; index++) { @@ -259,7 +259,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => trackInDatabase.Title.Should().Be(newTrackTitles[index]); - trackInDatabase.OwnedBy.ShouldNotBeNull(); + trackInDatabase.OwnedBy.Should().NotBeNull(); trackInDatabase.OwnedBy.Id.Should().Be(existingCompany.Id); } }); @@ -296,15 +296,15 @@ public async Task Cannot_create_for_null_relationship() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object, instead of 'null'."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/lyric"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -340,15 +340,15 @@ public async Task Cannot_create_for_missing_data_in_relationship() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'data' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/lyric"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -392,15 +392,15 @@ public async Task Cannot_create_for_array_data_in_relationship() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object or 'null', instead of an array."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/lyric/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -440,15 +440,15 @@ public async Task Cannot_create_for_missing_relationship_type() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/lyric/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -489,15 +489,15 @@ public async Task Cannot_create_for_unknown_relationship_type() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/lyric/data/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -537,22 +537,22 @@ public async Task Cannot_create_for_missing_relationship_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' or 'lid' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/lyric/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_with_unknown_relationship_ID() { // Arrange - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; string lyricId = Unknown.StringId.For(); @@ -594,13 +594,13 @@ public async Task Cannot_create_with_unknown_relationship_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); error.Title.Should().Be("A related resource does not exist."); error.Detail.Should().Be($"Related resource of type 'lyrics' with ID '{lyricId}' in relationship 'lyric' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); error.Meta.Should().NotContainKey("requestBody"); } @@ -643,23 +643,23 @@ public async Task Cannot_create_on_relationship_type_mismatch() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Incompatible resource type found."); error.Detail.Should().Be("Type 'playlists' is not convertible to type 'lyrics' of relationship 'lyric'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/lyric/data/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_create_resource_with_duplicate_relationship() { // Arrange - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -715,22 +715,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(1); + responseDocument.Results.Should().HaveCount(1); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("musicTracks"); - resource.Attributes.ShouldNotBeEmpty(); - resource.Relationships.ShouldNotBeEmpty(); + resource.Attributes.Should().NotBeEmpty(); + resource.Relationships.Should().NotBeEmpty(); }); - Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); + Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { MusicTrack trackInDatabase = await dbContext.MusicTracks.Include(musicTrack => musicTrack.OwnedBy).FirstWithIdAsync(newTrackId); - trackInDatabase.OwnedBy.ShouldNotBeNull(); + trackInDatabase.OwnedBy.Should().NotBeNull(); trackInDatabase.OwnedBy.Id.Should().Be(existingCompany.Id); }); } @@ -773,14 +773,14 @@ public async Task Cannot_assign_relationship_with_blocked_capability() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Relationship cannot be assigned."); error.Detail.Should().Be("The relationship 'language' on resource type 'lyrics' cannot be assigned to."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/language"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/DateMustBeInThePastAttribute.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/DateMustBeInThePastAttribute.cs index b273eca898..2a76f8ef34 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/DateMustBeInThePastAttribute.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/DateMustBeInThePastAttribute.cs @@ -2,7 +2,6 @@ using System.Reflection; using JsonApiDotNetCore.Resources; using Microsoft.Extensions.DependencyInjection; -using TestBuildingBlocks; namespace JsonApiDotNetCoreTests.IntegrationTests.AtomicOperations; @@ -20,9 +19,11 @@ internal sealed class DateMustBeInThePastAttribute : ValidationAttribute if (propertyInfo.PropertyType == typeof(DateTimeOffset) || propertyInfo.PropertyType == typeof(DateTimeOffset?)) { var typedValue = (DateTimeOffset?)propertyInfo.GetValue(validationContext.ObjectInstance); - var systemClock = validationContext.GetRequiredService(); - if (typedValue >= systemClock.UtcNow) + var timeProvider = validationContext.GetRequiredService(); + DateTimeOffset utcNow = timeProvider.GetUtcNow(); + + if (typedValue >= utcNow) { return new ValidationResult($"{validationContext.MemberName} must be in the past."); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Deleting/AtomicDeleteResourceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Deleting/AtomicDeleteResourceTests.cs index c2dc97b612..a330577dbd 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Deleting/AtomicDeleteResourceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Deleting/AtomicDeleteResourceTests.cs @@ -23,7 +23,7 @@ public AtomicDeleteResourceTests(IntegrationTestContext { @@ -71,7 +71,7 @@ public async Task Can_delete_existing_resources() // Arrange const int elementCount = 5; - List existingTracks = _fakers.MusicTrack.Generate(elementCount); + List existingTracks = _fakers.MusicTrack.GenerateList(elementCount); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -122,8 +122,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource_with_OneToOne_relationship_from_principal_side() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); - existingLyric.Track = _fakers.MusicTrack.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); + existingLyric.Track = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -173,8 +173,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource_with_OneToOne_relationship_from_dependent_side() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Lyric = _fakers.Lyric.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Lyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -224,8 +224,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_existing_resource_with_OneToMany_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Performers = _fakers.Performer.Generate(2); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Performers = _fakers.Performer.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -276,8 +276,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_existing_resource_with_ManyToMany_relationship() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); - existingPlaylist.Tracks = _fakers.MusicTrack.Generate(1); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); + existingPlaylist.Tracks = _fakers.MusicTrack.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -319,7 +319,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => MusicTrack? trackInDatabase = await dbContext.MusicTracks.FirstWithIdOrDefaultAsync(existingPlaylist.Tracks[0].Id); - trackInDatabase.ShouldNotBeNull(); + trackInDatabase.Should().NotBeNull(); }); } @@ -347,15 +347,15 @@ public async Task Cannot_delete_resource_for_href_element() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'href' element is not supported."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/href"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -381,15 +381,15 @@ public async Task Cannot_delete_resource_for_missing_ref_element() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'ref' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -419,15 +419,15 @@ public async Task Cannot_delete_resource_for_missing_type() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -458,15 +458,15 @@ public async Task Cannot_delete_resource_for_unknown_type() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -496,15 +496,15 @@ public async Task Cannot_delete_resource_for_missing_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' or 'lid' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -537,13 +537,13 @@ public async Task Cannot_delete_resource_for_unknown_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); error.Title.Should().Be("The requested resource does not exist."); error.Detail.Should().Be($"Resource of type 'performers' with ID '{performerId}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); error.Meta.Should().NotContainKey("requestBody"); } @@ -578,15 +578,15 @@ public async Task Cannot_delete_resource_for_incompatible_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Incompatible 'id' value found."); error.Detail.Should().Be($"Failed to convert '{guid}' of type 'String' to type 'Int64'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref/id"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -618,14 +618,14 @@ public async Task Cannot_delete_resource_for_ID_and_local_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' and 'lid' element are mutually exclusive."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Links/AtomicAbsoluteLinksTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Links/AtomicAbsoluteLinksTests.cs index 4b1ed95619..24423438bc 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Links/AtomicAbsoluteLinksTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Links/AtomicAbsoluteLinksTests.cs @@ -32,8 +32,8 @@ public AtomicAbsoluteLinksTests(IntegrationTestContext { @@ -80,37 +80,37 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(2); + responseDocument.Results.Should().HaveCount(2); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { string languageLink = $"{HostPrefix}/textLanguages/{existingLanguage.StringId}"; - resource.ShouldNotBeNull(); - resource.Links.ShouldNotBeNull(); + resource.Should().NotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(languageLink); - resource.Relationships.ShouldContainKey("lyrics").With(value => + resource.Relationships.Should().ContainKey("lyrics").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{languageLink}/relationships/lyrics"); value.Links.Related.Should().Be($"{languageLink}/lyrics"); }); }); - responseDocument.Results[1].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[1].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { string companyLink = $"{HostPrefix}/recordCompanies/{existingCompany.StringId}"; - resource.ShouldNotBeNull(); - resource.Links.ShouldNotBeNull(); + resource.Should().NotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(companyLink); - resource.Relationships.ShouldContainKey("tracks").With(value => + resource.Relationships.Should().ContainKey("tracks").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{companyLink}/relationships/tracks"); value.Links.Related.Should().Be($"{companyLink}/tracks"); }); @@ -121,7 +121,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Update_resource_with_side_effects_and_missing_resource_controller_hides_links() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -156,11 +156,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(1); + responseDocument.Results.Should().HaveCount(1); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { - resource.ShouldNotBeNull(); + resource.Should().NotBeNull(); resource.Links.Should().BeNull(); resource.Relationships.Should().BeNull(); }); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Links/AtomicRelativeLinksWithNamespaceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Links/AtomicRelativeLinksWithNamespaceTests.cs index 6d5a276ecb..6d5bd1797e 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Links/AtomicRelativeLinksWithNamespaceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Links/AtomicRelativeLinksWithNamespaceTests.cs @@ -33,7 +33,7 @@ public AtomicRelativeLinksWithNamespaceTests( public async Task Create_resource_with_side_effects_returns_relative_links() { // Arrange - string newCompanyName = _fakers.RecordCompany.Generate().Name; + string newCompanyName = _fakers.RecordCompany.GenerateOne().Name; var requestBody = new { @@ -73,39 +73,39 @@ public async Task Create_resource_with_side_effects_returns_relative_links() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(2); + responseDocument.Results.Should().HaveCount(2); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull(); + responseDocument.Results[0].Data.SingleValue.Should().NotBeNull(); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { - string languageLink = $"/api/textLanguages/{Guid.Parse(resource.Id.ShouldNotBeNull())}"; + string languageLink = $"/api/textLanguages/{Guid.Parse(resource.Id.Should().NotBeNull().And.Subject)}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(languageLink); - resource.Relationships.ShouldContainKey("lyrics").With(value => + resource.Relationships.Should().ContainKey("lyrics").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{languageLink}/relationships/lyrics"); value.Links.Related.Should().Be($"{languageLink}/lyrics"); }); }); - responseDocument.Results[1].Data.SingleValue.ShouldNotBeNull(); + responseDocument.Results[1].Data.SingleValue.Should().NotBeNull(); - responseDocument.Results[1].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[1].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { - string companyLink = $"/api/recordCompanies/{short.Parse(resource.Id.ShouldNotBeNull())}"; + string companyLink = $"/api/recordCompanies/{short.Parse(resource.Id.Should().NotBeNull().And.Subject)}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(companyLink); - resource.Relationships.ShouldContainKey("tracks").With(value => + resource.Relationships.Should().ContainKey("tracks").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{companyLink}/relationships/tracks"); value.Links.Related.Should().Be($"{companyLink}/tracks"); }); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/LocalIds/AtomicLocalIdTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/LocalIds/AtomicLocalIdTests.cs index df5bc5f90b..fb02b6df3f 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/LocalIds/AtomicLocalIdTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/LocalIds/AtomicLocalIdTests.cs @@ -23,8 +23,8 @@ public AtomicLocalIdTests(IntegrationTestContext + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("recordCompanies"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("name").With(value => value.Should().Be(newCompany.Name)); - resource.Attributes.ShouldContainKey("countryOfResidence").With(value => value.Should().Be(newCompany.CountryOfResidence)); + resource.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(newCompany.Name); + resource.Attributes.Should().ContainKey("countryOfResidence").WhoseValue.Should().Be(newCompany.CountryOfResidence); }); - responseDocument.Results[1].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[1].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("musicTracks"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("title").With(value => value.Should().Be(newTrackTitle)); + resource.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(newTrackTitle); }); - short newCompanyId = short.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); - Guid newTrackId = Guid.Parse(responseDocument.Results[1].Data.SingleValue!.Id.ShouldNotBeNull()); + short newCompanyId = short.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); + Guid newTrackId = Guid.Parse(responseDocument.Results[1].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -106,7 +106,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => trackInDatabase.Title.Should().Be(newTrackTitle); - trackInDatabase.OwnedBy.ShouldNotBeNull(); + trackInDatabase.OwnedBy.Should().NotBeNull(); trackInDatabase.OwnedBy.Id.Should().Be(newCompanyId); trackInDatabase.OwnedBy.Name.Should().Be(newCompany.Name); trackInDatabase.OwnedBy.CountryOfResidence.Should().Be(newCompany.CountryOfResidence); @@ -117,8 +117,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_resource_with_OneToMany_relationship_using_local_ID() { // Arrange - Performer newPerformer = _fakers.Performer.Generate(); - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + Performer newPerformer = _fakers.Performer.GenerateOne(); + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; const string performerLocalId = "performer-1"; @@ -177,25 +177,25 @@ public async Task Can_create_resource_with_OneToMany_relationship_using_local_ID // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(2); + responseDocument.Results.Should().HaveCount(2); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("performers"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("artistName").With(value => value.Should().Be(newPerformer.ArtistName)); - resource.Attributes.ShouldContainKey("bornAt").With(value => value.Should().Be(newPerformer.BornAt)); + resource.Attributes.Should().ContainKey("artistName").WhoseValue.Should().Be(newPerformer.ArtistName); + resource.Attributes.Should().ContainKey("bornAt").WhoseValue.Should().Be(newPerformer.BornAt); }); - responseDocument.Results[1].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[1].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("musicTracks"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("title").With(value => value.Should().Be(newTrackTitle)); + resource.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(newTrackTitle); }); - int newPerformerId = int.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); - Guid newTrackId = Guid.Parse(responseDocument.Results[1].Data.SingleValue!.Id.ShouldNotBeNull()); + int newPerformerId = int.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); + Guid newTrackId = Guid.Parse(responseDocument.Results[1].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -203,7 +203,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => trackInDatabase.Title.Should().Be(newTrackTitle); - trackInDatabase.Performers.ShouldHaveCount(1); + trackInDatabase.Performers.Should().HaveCount(1); trackInDatabase.Performers[0].Id.Should().Be(newPerformerId); trackInDatabase.Performers[0].ArtistName.Should().Be(newPerformer.ArtistName); trackInDatabase.Performers[0].BornAt.Should().Be(newPerformer.BornAt); @@ -214,8 +214,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_resource_with_ManyToMany_relationship_using_local_ID() { // Arrange - string newTrackTitle = _fakers.MusicTrack.Generate().Title; - string newPlaylistName = _fakers.Playlist.Generate().Name; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; + string newPlaylistName = _fakers.Playlist.GenerateOne().Name; const string trackLocalId = "track-1"; @@ -273,24 +273,24 @@ public async Task Can_create_resource_with_ManyToMany_relationship_using_local_I // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(2); + responseDocument.Results.Should().HaveCount(2); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("musicTracks"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("title").With(value => value.Should().Be(newTrackTitle)); + resource.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(newTrackTitle); }); - responseDocument.Results[1].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[1].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("playlists"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("name").With(value => value.Should().Be(newPlaylistName)); + resource.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(newPlaylistName); }); - Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); - long newPlaylistId = long.Parse(responseDocument.Results[1].Data.SingleValue!.Id.ShouldNotBeNull()); + Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); + long newPlaylistId = long.Parse(responseDocument.Results[1].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -298,7 +298,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => playlistInDatabase.Name.Should().Be(newPlaylistName); - playlistInDatabase.Tracks.ShouldHaveCount(1); + playlistInDatabase.Tracks.Should().HaveCount(1); playlistInDatabase.Tracks[0].Id.Should().Be(newTrackId); playlistInDatabase.Tracks[0].Title.Should().Be(newTrackTitle); }); @@ -310,7 +310,7 @@ public async Task Cannot_consume_local_ID_that_is_assigned_in_same_operation() // Arrange const string companyLocalId = "company-1"; - string newCompanyName = _fakers.RecordCompany.Generate().Name; + string newCompanyName = _fakers.RecordCompany.GenerateOne().Name; var requestBody = new { @@ -360,13 +360,13 @@ public async Task Cannot_consume_local_ID_that_is_assigned_in_same_operation() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Local ID cannot be both defined and used within the same operation."); error.Detail.Should().Be("Local ID 'company-1' cannot be both defined and used within the same operation."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[1]"); } @@ -374,7 +374,7 @@ public async Task Cannot_consume_local_ID_that_is_assigned_in_same_operation() public async Task Cannot_reassign_local_ID() { // Arrange - string newPlaylistName = _fakers.Playlist.Generate().Name; + string newPlaylistName = _fakers.Playlist.GenerateOne().Name; const string playlistLocalId = "playlist-1"; var requestBody = new @@ -427,13 +427,13 @@ public async Task Cannot_reassign_local_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Another local ID with the same name is already defined at this point."); error.Detail.Should().Be("Another local ID with name 'playlist-1' is already defined at this point."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[2]"); } @@ -441,8 +441,8 @@ public async Task Cannot_reassign_local_ID() public async Task Can_update_resource_using_local_ID() { // Arrange - string newTrackTitle = _fakers.MusicTrack.Generate().Title; - string newTrackGenre = _fakers.MusicTrack.Generate().Genre!; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; + string newTrackGenre = _fakers.MusicTrack.GenerateOne().Genre!; const string trackLocalId = "track-1"; @@ -487,19 +487,19 @@ public async Task Can_update_resource_using_local_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(2); + responseDocument.Results.Should().HaveCount(2); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("musicTracks"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("title").With(value => value.Should().Be(newTrackTitle)); - resource.Attributes.ShouldContainKey("genre").With(value => value.Should().BeNull()); + resource.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(newTrackTitle); + resource.Attributes.Should().ContainKey("genre").WhoseValue.Should().BeNull(); }); responseDocument.Results[1].Data.Value.Should().BeNull(); - Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); + Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -514,9 +514,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_relationships_using_local_ID() { // Arrange - string newTrackTitle = _fakers.MusicTrack.Generate().Title; - string newArtistName = _fakers.Performer.Generate().ArtistName!; - string newCompanyName = _fakers.RecordCompany.Generate().Name; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; + string newArtistName = _fakers.Performer.GenerateOne().ArtistName!; + string newCompanyName = _fakers.RecordCompany.GenerateOne().Name; const string trackLocalId = "track-1"; const string performerLocalId = "performer-1"; @@ -607,34 +607,34 @@ public async Task Can_update_resource_with_relationships_using_local_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(4); + responseDocument.Results.Should().HaveCount(4); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("musicTracks"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("title").With(value => value.Should().Be(newTrackTitle)); + resource.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(newTrackTitle); }); - responseDocument.Results[1].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[1].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("performers"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("artistName").With(value => value.Should().Be(newArtistName)); + resource.Attributes.Should().ContainKey("artistName").WhoseValue.Should().Be(newArtistName); }); - responseDocument.Results[2].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[2].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("recordCompanies"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("name").With(value => value.Should().Be(newCompanyName)); + resource.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(newCompanyName); }); responseDocument.Results[3].Data.Value.Should().BeNull(); - Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); - int newPerformerId = int.Parse(responseDocument.Results[1].Data.SingleValue!.Id.ShouldNotBeNull()); - short newCompanyId = short.Parse(responseDocument.Results[2].Data.SingleValue!.Id.ShouldNotBeNull()); + Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); + int newPerformerId = int.Parse(responseDocument.Results[1].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); + short newCompanyId = short.Parse(responseDocument.Results[2].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -651,10 +651,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => trackInDatabase.Title.Should().Be(newTrackTitle); - trackInDatabase.OwnedBy.ShouldNotBeNull(); + trackInDatabase.OwnedBy.Should().NotBeNull(); trackInDatabase.OwnedBy.Id.Should().Be(newCompanyId); - trackInDatabase.Performers.ShouldHaveCount(1); + trackInDatabase.Performers.Should().HaveCount(1); trackInDatabase.Performers[0].Id.Should().Be(newPerformerId); trackInDatabase.Performers[0].ArtistName.Should().Be(newArtistName); }); @@ -664,8 +664,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_ManyToOne_relationship_using_local_ID() { // Arrange - string newTrackTitle = _fakers.MusicTrack.Generate().Title; - string newCompanyName = _fakers.RecordCompany.Generate().Name; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; + string newCompanyName = _fakers.RecordCompany.GenerateOne().Name; const string trackLocalId = "track-1"; const string companyLocalId = "company-1"; @@ -726,26 +726,26 @@ public async Task Can_create_ManyToOne_relationship_using_local_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(3); + responseDocument.Results.Should().HaveCount(3); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("musicTracks"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("title").With(value => value.Should().Be(newTrackTitle)); + resource.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(newTrackTitle); }); - responseDocument.Results[1].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[1].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("recordCompanies"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("name").With(value => value.Should().Be(newCompanyName)); + resource.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(newCompanyName); }); responseDocument.Results[2].Data.Value.Should().BeNull(); - Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); - short newCompanyId = short.Parse(responseDocument.Results[1].Data.SingleValue!.Id.ShouldNotBeNull()); + Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); + short newCompanyId = short.Parse(responseDocument.Results[1].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -753,7 +753,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => trackInDatabase.Title.Should().Be(newTrackTitle); - trackInDatabase.OwnedBy.ShouldNotBeNull(); + trackInDatabase.OwnedBy.Should().NotBeNull(); trackInDatabase.OwnedBy.Id.Should().Be(newCompanyId); trackInDatabase.OwnedBy.Name.Should().Be(newCompanyName); }); @@ -763,8 +763,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToMany_relationship_using_local_ID() { // Arrange - string newTrackTitle = _fakers.MusicTrack.Generate().Title; - string newArtistName = _fakers.Performer.Generate().ArtistName!; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; + string newArtistName = _fakers.Performer.GenerateOne().ArtistName!; const string trackLocalId = "track-1"; const string performerLocalId = "performer-1"; @@ -828,26 +828,26 @@ public async Task Can_create_OneToMany_relationship_using_local_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(3); + responseDocument.Results.Should().HaveCount(3); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("musicTracks"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("title").With(value => value.Should().Be(newTrackTitle)); + resource.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(newTrackTitle); }); - responseDocument.Results[1].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[1].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("performers"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("artistName").With(value => value.Should().Be(newArtistName)); + resource.Attributes.Should().ContainKey("artistName").WhoseValue.Should().Be(newArtistName); }); responseDocument.Results[2].Data.Value.Should().BeNull(); - Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); - int newPerformerId = int.Parse(responseDocument.Results[1].Data.SingleValue!.Id.ShouldNotBeNull()); + Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); + int newPerformerId = int.Parse(responseDocument.Results[1].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -855,7 +855,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => trackInDatabase.Title.Should().Be(newTrackTitle); - trackInDatabase.Performers.ShouldHaveCount(1); + trackInDatabase.Performers.Should().HaveCount(1); trackInDatabase.Performers[0].Id.Should().Be(newPerformerId); trackInDatabase.Performers[0].ArtistName.Should().Be(newArtistName); }); @@ -865,8 +865,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_ManyToMany_relationship_using_local_ID() { // Arrange - string newPlaylistName = _fakers.Playlist.Generate().Name; - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newPlaylistName = _fakers.Playlist.GenerateOne().Name; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; const string playlistLocalId = "playlist-1"; const string trackLocalId = "track-1"; @@ -930,26 +930,26 @@ public async Task Can_create_ManyToMany_relationship_using_local_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(3); + responseDocument.Results.Should().HaveCount(3); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("playlists"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("name").With(value => value.Should().Be(newPlaylistName)); + resource.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(newPlaylistName); }); - responseDocument.Results[1].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[1].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("musicTracks"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("title").With(value => value.Should().Be(newTrackTitle)); + resource.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(newTrackTitle); }); responseDocument.Results[2].Data.Value.Should().BeNull(); - long newPlaylistId = long.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); - Guid newTrackId = Guid.Parse(responseDocument.Results[1].Data.SingleValue!.Id.ShouldNotBeNull()); + long newPlaylistId = long.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); + Guid newTrackId = Guid.Parse(responseDocument.Results[1].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -957,7 +957,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => playlistInDatabase.Name.Should().Be(newPlaylistName); - playlistInDatabase.Tracks.ShouldHaveCount(1); + playlistInDatabase.Tracks.Should().HaveCount(1); playlistInDatabase.Tracks[0].Id.Should().Be(newTrackId); playlistInDatabase.Tracks[0].Title.Should().Be(newTrackTitle); }); @@ -967,10 +967,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToMany_relationship_using_local_ID() { // Arrange - Performer existingPerformer = _fakers.Performer.Generate(); + Performer existingPerformer = _fakers.Performer.GenerateOne(); - string newTrackTitle = _fakers.MusicTrack.Generate().Title; - string newArtistName = _fakers.Performer.Generate().ArtistName!; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; + string newArtistName = _fakers.Performer.GenerateOne().ArtistName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1054,26 +1054,26 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(3); + responseDocument.Results.Should().HaveCount(3); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("musicTracks"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("title").With(value => value.Should().Be(newTrackTitle)); + resource.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(newTrackTitle); }); - responseDocument.Results[1].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[1].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("performers"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("artistName").With(value => value.Should().Be(newArtistName)); + resource.Attributes.Should().ContainKey("artistName").WhoseValue.Should().Be(newArtistName); }); responseDocument.Results[2].Data.Value.Should().BeNull(); - Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); - int newPerformerId = int.Parse(responseDocument.Results[1].Data.SingleValue!.Id.ShouldNotBeNull()); + Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); + int newPerformerId = int.Parse(responseDocument.Results[1].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1081,7 +1081,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => trackInDatabase.Title.Should().Be(newTrackTitle); - trackInDatabase.Performers.ShouldHaveCount(1); + trackInDatabase.Performers.Should().HaveCount(1); trackInDatabase.Performers[0].Id.Should().Be(newPerformerId); trackInDatabase.Performers[0].ArtistName.Should().Be(newArtistName); }); @@ -1091,10 +1091,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ManyToMany_relationship_using_local_ID() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); - string newPlaylistName = _fakers.Playlist.Generate().Name; - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newPlaylistName = _fakers.Playlist.GenerateOne().Name; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1178,26 +1178,26 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(3); + responseDocument.Results.Should().HaveCount(3); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("playlists"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("name").With(value => value.Should().Be(newPlaylistName)); + resource.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(newPlaylistName); }); - responseDocument.Results[1].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[1].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("musicTracks"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("title").With(value => value.Should().Be(newTrackTitle)); + resource.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(newTrackTitle); }); responseDocument.Results[2].Data.Value.Should().BeNull(); - long newPlaylistId = long.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); - Guid newTrackId = Guid.Parse(responseDocument.Results[1].Data.SingleValue!.Id.ShouldNotBeNull()); + long newPlaylistId = long.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); + Guid newTrackId = Guid.Parse(responseDocument.Results[1].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1205,7 +1205,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => playlistInDatabase.Name.Should().Be(newPlaylistName); - playlistInDatabase.Tracks.ShouldHaveCount(1); + playlistInDatabase.Tracks.Should().HaveCount(1); playlistInDatabase.Tracks[0].Id.Should().Be(newTrackId); playlistInDatabase.Tracks[0].Title.Should().Be(newTrackTitle); }); @@ -1215,10 +1215,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_to_OneToMany_relationship_using_local_ID() { // Arrange - Performer existingPerformer = _fakers.Performer.Generate(); + Performer existingPerformer = _fakers.Performer.GenerateOne(); - string newTrackTitle = _fakers.MusicTrack.Generate().Title; - string newArtistName = _fakers.Performer.Generate().ArtistName!; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; + string newArtistName = _fakers.Performer.GenerateOne().ArtistName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1302,26 +1302,26 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(3); + responseDocument.Results.Should().HaveCount(3); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("musicTracks"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("title").With(value => value.Should().Be(newTrackTitle)); + resource.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(newTrackTitle); }); - responseDocument.Results[1].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[1].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("performers"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("artistName").With(value => value.Should().Be(newArtistName)); + resource.Attributes.Should().ContainKey("artistName").WhoseValue.Should().Be(newArtistName); }); responseDocument.Results[2].Data.Value.Should().BeNull(); - Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); - int newPerformerId = int.Parse(responseDocument.Results[1].Data.SingleValue!.Id.ShouldNotBeNull()); + Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); + int newPerformerId = int.Parse(responseDocument.Results[1].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1329,7 +1329,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => trackInDatabase.Title.Should().Be(newTrackTitle); - trackInDatabase.Performers.ShouldHaveCount(2); + trackInDatabase.Performers.Should().HaveCount(2); trackInDatabase.Performers[0].Id.Should().Be(existingPerformer.Id); trackInDatabase.Performers[0].ArtistName.Should().Be(existingPerformer.ArtistName); @@ -1343,10 +1343,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_to_ManyToMany_relationship_using_local_ID() { // Arrange - List existingTracks = _fakers.MusicTrack.Generate(2); + List existingTracks = _fakers.MusicTrack.GenerateList(2); - string newPlaylistName = _fakers.Playlist.Generate().Name; - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newPlaylistName = _fakers.Playlist.GenerateOne().Name; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; const string playlistLocalId = "playlist-1"; const string trackLocalId = "track-1"; @@ -1448,28 +1448,28 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(4); + responseDocument.Results.Should().HaveCount(4); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("playlists"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("name").With(value => value.Should().Be(newPlaylistName)); + resource.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(newPlaylistName); }); - responseDocument.Results[1].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[1].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("musicTracks"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("title").With(value => value.Should().Be(newTrackTitle)); + resource.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(newTrackTitle); }); responseDocument.Results[2].Data.Value.Should().BeNull(); responseDocument.Results[3].Data.Value.Should().BeNull(); - long newPlaylistId = long.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); - Guid newTrackId = Guid.Parse(responseDocument.Results[1].Data.SingleValue!.Id.ShouldNotBeNull()); + long newPlaylistId = long.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); + Guid newTrackId = Guid.Parse(responseDocument.Results[1].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1477,7 +1477,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => playlistInDatabase.Name.Should().Be(newPlaylistName); - playlistInDatabase.Tracks.ShouldHaveCount(3); + playlistInDatabase.Tracks.Should().HaveCount(3); playlistInDatabase.Tracks.Should().ContainSingle(musicTrack => musicTrack.Id == existingTracks[0].Id); playlistInDatabase.Tracks.Should().ContainSingle(musicTrack => musicTrack.Id == existingTracks[1].Id); playlistInDatabase.Tracks.Should().ContainSingle(musicTrack => musicTrack.Id == newTrackId); @@ -1488,11 +1488,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_OneToMany_relationship_using_local_ID() { // Arrange - Performer existingPerformer = _fakers.Performer.Generate(); + Performer existingPerformer = _fakers.Performer.GenerateOne(); - string newTrackTitle = _fakers.MusicTrack.Generate().Title; - string newArtistName1 = _fakers.Performer.Generate().ArtistName!; - string newArtistName2 = _fakers.Performer.Generate().ArtistName!; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; + string newArtistName1 = _fakers.Performer.GenerateOne().ArtistName!; + string newArtistName2 = _fakers.Performer.GenerateOne().ArtistName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1605,32 +1605,32 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(4); + responseDocument.Results.Should().HaveCount(4); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("performers"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("artistName").With(value => value.Should().Be(newArtistName1)); + resource.Attributes.Should().ContainKey("artistName").WhoseValue.Should().Be(newArtistName1); }); - responseDocument.Results[1].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[1].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("performers"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("artistName").With(value => value.Should().Be(newArtistName2)); + resource.Attributes.Should().ContainKey("artistName").WhoseValue.Should().Be(newArtistName2); }); - responseDocument.Results[2].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[2].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("musicTracks"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("title").With(value => value.Should().Be(newTrackTitle)); + resource.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(newTrackTitle); }); responseDocument.Results[3].Data.Value.Should().BeNull(); - Guid newTrackId = Guid.Parse(responseDocument.Results[2].Data.SingleValue!.Id.ShouldNotBeNull()); + Guid newTrackId = Guid.Parse(responseDocument.Results[2].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1638,7 +1638,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => trackInDatabase.Title.Should().Be(newTrackTitle); - trackInDatabase.Performers.ShouldHaveCount(1); + trackInDatabase.Performers.Should().HaveCount(1); trackInDatabase.Performers[0].Id.Should().Be(existingPerformer.Id); trackInDatabase.Performers[0].ArtistName.Should().Be(existingPerformer.ArtistName); }); @@ -1648,10 +1648,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_ManyToMany_relationship_using_local_ID() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); - existingPlaylist.Tracks = _fakers.MusicTrack.Generate(2); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); + existingPlaylist.Tracks = _fakers.MusicTrack.GenerateList(2); - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; const string trackLocalId = "track-1"; @@ -1743,13 +1743,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(4); + responseDocument.Results.Should().HaveCount(4); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("musicTracks"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("title").With(value => value.Should().Be(newTrackTitle)); + resource.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(newTrackTitle); }); responseDocument.Results[1].Data.Value.Should().BeNull(); @@ -1762,7 +1762,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Playlist playlistInDatabase = await dbContext.Playlists.Include(playlist => playlist.Tracks).FirstWithIdAsync(existingPlaylist.Id); - playlistInDatabase.Tracks.ShouldHaveCount(1); + playlistInDatabase.Tracks.Should().HaveCount(1); playlistInDatabase.Tracks[0].Id.Should().Be(existingPlaylist.Tracks[0].Id); }); } @@ -1771,7 +1771,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource_using_local_ID() { // Arrange - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; const string trackLocalId = "track-1"; @@ -1812,18 +1812,18 @@ public async Task Can_delete_resource_using_local_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(2); + responseDocument.Results.Should().HaveCount(2); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("musicTracks"); resource.Lid.Should().BeNull(); - resource.Attributes.ShouldContainKey("title").With(value => value.Should().Be(newTrackTitle)); + resource.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(newTrackTitle); }); responseDocument.Results[1].Data.Value.Should().BeNull(); - Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.ShouldNotBeNull()); + Guid newTrackId = Guid.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1870,13 +1870,13 @@ public async Task Cannot_consume_unassigned_local_ID_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Server-generated value for local ID is not available at this point."); error.Detail.Should().Be($"Server-generated value for local ID '{Unknown.LocalId}' is not available at this point."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[1]"); } @@ -1920,13 +1920,13 @@ public async Task Cannot_consume_unassigned_local_ID_in_data_element() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Server-generated value for local ID is not available at this point."); error.Detail.Should().Be($"Server-generated value for local ID '{Unknown.LocalId}' is not available at this point."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[1]"); } @@ -1934,7 +1934,7 @@ public async Task Cannot_consume_unassigned_local_ID_in_data_element() public async Task Cannot_consume_unassigned_local_ID_in_data_array() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1984,13 +1984,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Server-generated value for local ID is not available at this point."); error.Detail.Should().Be($"Server-generated value for local ID '{Unknown.LocalId}' is not available at this point."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[1]"); } @@ -1998,7 +1998,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_consume_unassigned_local_ID_in_relationship_data_element() { // Arrange - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; var requestBody = new { @@ -2047,13 +2047,13 @@ public async Task Cannot_consume_unassigned_local_ID_in_relationship_data_elemen // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Server-generated value for local ID is not available at this point."); error.Detail.Should().Be($"Server-generated value for local ID '{Unknown.LocalId}' is not available at this point."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[1]"); } @@ -2061,7 +2061,7 @@ public async Task Cannot_consume_unassigned_local_ID_in_relationship_data_elemen public async Task Cannot_consume_unassigned_local_ID_in_relationship_data_array() { // Arrange - string newPlaylistName = _fakers.Playlist.Generate().Name; + string newPlaylistName = _fakers.Playlist.GenerateOne().Name; var requestBody = new { @@ -2113,13 +2113,13 @@ public async Task Cannot_consume_unassigned_local_ID_in_relationship_data_array( // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Server-generated value for local ID is not available at this point."); error.Detail.Should().Be($"Server-generated value for local ID '{Unknown.LocalId}' is not available at this point."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[1]"); } @@ -2128,7 +2128,7 @@ public async Task Cannot_consume_local_ID_of_different_type_in_same_operation() { // Arrange const string trackLocalId = "track-1"; - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; var requestBody = new { @@ -2178,13 +2178,13 @@ public async Task Cannot_consume_local_ID_of_different_type_in_same_operation() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Incompatible type in Local ID usage."); error.Detail.Should().Be("Local ID 'track-1' belongs to resource type 'musicTracks' instead of 'recordCompanies'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[1]"); } @@ -2194,7 +2194,7 @@ public async Task Cannot_consume_local_ID_of_different_type_in_ref() // Arrange const string companyLocalId = "company-1"; - string newCompanyName = _fakers.RecordCompany.Generate().Name; + string newCompanyName = _fakers.RecordCompany.GenerateOne().Name; var requestBody = new { @@ -2242,13 +2242,13 @@ public async Task Cannot_consume_local_ID_of_different_type_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Incompatible type in Local ID usage."); error.Detail.Should().Be("Local ID 'company-1' belongs to resource type 'recordCompanies' instead of 'musicTracks'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[2]"); } @@ -2303,13 +2303,13 @@ public async Task Cannot_consume_local_ID_of_different_type_in_data_element() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Incompatible type in Local ID usage."); error.Detail.Should().Be("Local ID 'performer-1' belongs to resource type 'performers' instead of 'playlists'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[2]"); } @@ -2317,11 +2317,11 @@ public async Task Cannot_consume_local_ID_of_different_type_in_data_element() public async Task Cannot_consume_local_ID_of_different_type_in_data_array() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); const string companyLocalId = "company-1"; - string newCompanyName = _fakers.RecordCompany.Generate().Name; + string newCompanyName = _fakers.RecordCompany.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2384,13 +2384,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Incompatible type in Local ID usage."); error.Detail.Should().Be("Local ID 'company-1' belongs to resource type 'recordCompanies' instead of 'performers'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[2]"); } @@ -2398,8 +2398,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_consume_local_ID_of_different_type_in_relationship_data_element() { // Arrange - string newPlaylistName = _fakers.Playlist.Generate().Name; - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newPlaylistName = _fakers.Playlist.GenerateOne().Name; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; const string playlistLocalId = "playlist-1"; @@ -2463,13 +2463,13 @@ public async Task Cannot_consume_local_ID_of_different_type_in_relationship_data // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Incompatible type in Local ID usage."); error.Detail.Should().Be("Local ID 'playlist-1' belongs to resource type 'playlists' instead of 'recordCompanies'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[2]"); } @@ -2478,7 +2478,7 @@ public async Task Cannot_consume_local_ID_of_different_type_in_relationship_data { // Arrange const string performerLocalId = "performer-1"; - string newPlaylistName = _fakers.Playlist.Generate().Name; + string newPlaylistName = _fakers.Playlist.GenerateOne().Name; var requestBody = new { @@ -2539,13 +2539,13 @@ public async Task Cannot_consume_local_ID_of_different_type_in_relationship_data // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Incompatible type in Local ID usage."); error.Detail.Should().Be("Local ID 'performer-1' belongs to resource type 'performers' instead of 'musicTracks'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[2]"); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Meta/AtomicResourceMetaTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Meta/AtomicResourceMetaTests.cs index f98bc1b49d..1ab1d848ac 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Meta/AtomicResourceMetaTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Meta/AtomicResourceMetaTests.cs @@ -27,7 +27,6 @@ public AtomicResourceMetaTests(IntegrationTestContext(); services.AddSingleton(); - services.AddSingleton(); }); var hitCounter = _testContext.Factory.Services.GetRequiredService(); @@ -40,8 +39,8 @@ public async Task Returns_resource_meta_in_create_resource_with_side_effects() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - string newTitle1 = _fakers.MusicTrack.Generate().Title; - string newTitle2 = _fakers.MusicTrack.Generate().Title; + string newTitle1 = _fakers.MusicTrack.GenerateOne().Title; + string newTitle2 = _fakers.MusicTrack.GenerateOne().Title; var requestBody = new { @@ -84,24 +83,24 @@ public async Task Returns_resource_meta_in_create_resource_with_side_effects() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(2); + responseDocument.Results.Should().HaveCount(2); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { - resource.Meta.ShouldHaveCount(1); + resource.Meta.Should().HaveCount(1); - resource.Meta.ShouldContainKey("copyright").With(value => + resource.Meta.Should().ContainKey("copyright").WhoseValue.With(value => { JsonElement element = value.Should().BeOfType().Subject; element.GetString().Should().Be("(C) 2018. All rights reserved."); }); }); - responseDocument.Results[1].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[1].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { - resource.Meta.ShouldHaveCount(1); + resource.Meta.Should().HaveCount(1); - resource.Meta.ShouldContainKey("copyright").With(value => + resource.Meta.Should().ContainKey("copyright").WhoseValue.With(value => { JsonElement element = value.Should().BeOfType().Subject; element.GetString().Should().Be("(C) 1994. All rights reserved."); @@ -121,7 +120,7 @@ public async Task Returns_resource_meta_in_update_resource_with_side_effects() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - TextLanguage existingLanguage = _fakers.TextLanguage.Generate(); + TextLanguage existingLanguage = _fakers.TextLanguage.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -156,13 +155,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(1); + responseDocument.Results.Should().HaveCount(1); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { - resource.Meta.ShouldHaveCount(1); + resource.Meta.Should().HaveCount(1); - resource.Meta.ShouldContainKey("notice").With(value => + resource.Meta.Should().ContainKey("notice").WhoseValue.With(value => { JsonElement element = value.Should().BeOfType().Subject; element.GetString().Should().Be(TextLanguageMetaDefinition.NoticeText); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Meta/AtomicResponseMetaTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Meta/AtomicResponseMetaTests.cs index e4c31db1e6..b111ee47fb 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Meta/AtomicResponseMetaTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Meta/AtomicResponseMetaTests.cs @@ -60,26 +60,26 @@ public async Task Returns_top_level_meta_in_create_resource_with_side_effects() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Meta.ShouldHaveCount(3); + responseDocument.Meta.Should().HaveCount(3); - responseDocument.Meta.ShouldContainKey("license").With(value => + responseDocument.Meta.Should().ContainKey("license").WhoseValue.With(value => { JsonElement element = value.Should().BeOfType().Subject; element.GetString().Should().Be("MIT"); }); - responseDocument.Meta.ShouldContainKey("projectUrl").With(value => + responseDocument.Meta.Should().ContainKey("projectUrl").WhoseValue.With(value => { JsonElement element = value.Should().BeOfType().Subject; element.GetString().Should().Be("https://github.com/json-api-dotnet/JsonApiDotNetCore/"); }); - responseDocument.Meta.ShouldContainKey("versions").With(value => + responseDocument.Meta.Should().ContainKey("versions").WhoseValue.With(value => { JsonElement element = value.Should().BeOfType().Subject; string?[] versionArray = element.EnumerateArray().Select(arrayItem => arrayItem.GetString()).ToArray(); - versionArray.ShouldHaveCount(4); + versionArray.Should().HaveCount(4); versionArray.Should().Contain("v4.0.0"); versionArray.Should().Contain("v3.1.0"); versionArray.Should().Contain("v2.5.2"); @@ -91,7 +91,7 @@ public async Task Returns_top_level_meta_in_create_resource_with_side_effects() public async Task Returns_top_level_meta_in_update_resource_with_side_effects() { // Arrange - TextLanguage existingLanguage = _fakers.TextLanguage.Generate(); + TextLanguage existingLanguage = _fakers.TextLanguage.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -126,26 +126,26 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Meta.ShouldHaveCount(3); + responseDocument.Meta.Should().HaveCount(3); - responseDocument.Meta.ShouldContainKey("license").With(value => + responseDocument.Meta.Should().ContainKey("license").WhoseValue.With(value => { JsonElement element = value.Should().BeOfType().Subject; element.GetString().Should().Be("MIT"); }); - responseDocument.Meta.ShouldContainKey("projectUrl").With(value => + responseDocument.Meta.Should().ContainKey("projectUrl").WhoseValue.With(value => { JsonElement element = value.Should().BeOfType().Subject; element.GetString().Should().Be("https://github.com/json-api-dotnet/JsonApiDotNetCore/"); }); - responseDocument.Meta.ShouldContainKey("versions").With(value => + responseDocument.Meta.Should().ContainKey("versions").WhoseValue.With(value => { JsonElement element = value.Should().BeOfType().Subject; string?[] versionArray = element.EnumerateArray().Select(arrayItem => arrayItem.GetString()).ToArray(); - versionArray.ShouldHaveCount(4); + versionArray.Should().HaveCount(4); versionArray.Should().Contain("v4.0.0"); versionArray.Should().Contain("v3.1.0"); versionArray.Should().Contain("v2.5.2"); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicLoggingTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicLoggingTests.cs index 412a3f388c..1662f9387f 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicLoggingTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicLoggingTests.cs @@ -19,28 +19,24 @@ public AtomicLoggingTests(IntegrationTestContext(); - var loggerFactory = new FakeLoggerFactory(LogLevel.Information); - testContext.ConfigureLogging(options => { - options.ClearProviders(); - options.AddProvider(loggerFactory); + var loggerProvider = new CapturingLoggerProvider(LogLevel.Information); + options.AddProvider(loggerProvider); options.SetMinimumLevel(LogLevel.Information); - }); - testContext.ConfigureServices(services => - { - services.AddSingleton(loggerFactory); - services.AddSingleton(); + options.Services.AddSingleton(loggerProvider); }); + + testContext.ConfigureServices(services => services.AddSingleton()); } [Fact] public async Task Logs_unhandled_exception_at_Error_level() { // Arrange - var loggerFactory = _testContext.Factory.Services.GetRequiredService(); - loggerFactory.Logger.Clear(); + var loggerProvider = _testContext.Factory.Services.GetRequiredService(); + loggerProvider.Clear(); var transactionFactory = (ThrowingOperationsTransactionFactory)_testContext.Factory.Services.GetRequiredService(); transactionFactory.ThrowOnOperationStart = true; @@ -71,28 +67,27 @@ public async Task Logs_unhandled_exception_at_Error_level() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.InternalServerError); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.InternalServerError); error.Title.Should().Be("An unhandled error occurred while processing an operation in this request."); error.Detail.Should().Be("Simulated failure."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); - IReadOnlyList logMessages = loggerFactory.Logger.GetMessages(); - logMessages.ShouldNotBeEmpty(); + IReadOnlyList logMessages = loggerProvider.GetMessages(); - logMessages.Should().ContainSingle(message => message.LogLevel == LogLevel.Error && - message.Text.Contains("Simulated failure.", StringComparison.Ordinal)); + logMessages.Should().ContainSingle(message => + message.LogLevel == LogLevel.Error && message.Text.Contains("Simulated failure.", StringComparison.Ordinal)); } [Fact] public async Task Logs_invalid_request_body_error_at_Information_level() { // Arrange - var loggerFactory = _testContext.Factory.Services.GetRequiredService(); - loggerFactory.Logger.Clear(); + var loggerProvider = _testContext.Factory.Services.GetRequiredService(); + loggerProvider.Clear(); var transactionFactory = (ThrowingOperationsTransactionFactory)_testContext.Factory.Services.GetRequiredService(); transactionFactory.ThrowOnOperationStart = false; @@ -116,10 +111,9 @@ public async Task Logs_invalid_request_body_error_at_Information_level() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); - IReadOnlyList logMessages = loggerFactory.Logger.GetMessages(); - logMessages.ShouldNotBeEmpty(); + IReadOnlyList logMessages = loggerProvider.GetMessages(); logMessages.Should().ContainSingle(message => message.LogLevel == LogLevel.Information && message.Text.Contains("Failed to deserialize request body", StringComparison.Ordinal)); @@ -165,7 +159,7 @@ private Task ThrowIfEnabled() { if (_owner.ThrowOnOperationStart) { - throw new Exception("Simulated failure."); + throw new InvalidOperationException("Simulated failure."); } return Task.CompletedTask; diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicRequestBodyTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicRequestBodyTests.cs index c4416bbac1..abc4525b60 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicRequestBodyTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicRequestBodyTests.cs @@ -30,10 +30,10 @@ public async Task Cannot_process_for_missing_request_body() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - httpResponse.Content.Headers.ContentType.ShouldNotBeNull(); - httpResponse.Content.Headers.ContentType.ToString().Should().Be(HeaderConstants.AtomicOperationsMediaType); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.AtomicOperations.ToString()); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); @@ -57,14 +57,14 @@ public async Task Cannot_process_for_null_request_body() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object, instead of 'null'."); error.Detail.Should().BeNull(); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -81,7 +81,7 @@ public async Task Cannot_process_for_broken_JSON_request_body() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); @@ -110,14 +110,14 @@ public async Task Cannot_process_for_missing_operations_array() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: No operations found."); error.Detail.Should().BeNull(); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -137,14 +137,14 @@ public async Task Cannot_process_empty_operations_array() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: No operations found."); error.Detail.Should().BeNull(); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -167,15 +167,15 @@ public async Task Cannot_process_null_operation() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object, instead of 'null'."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -208,7 +208,7 @@ public async Task Cannot_process_for_unknown_operation_code() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicSerializationTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicSerializationTests.cs index fc6d366f94..0d0a54bc58 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicSerializationTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicSerializationTests.cs @@ -38,9 +38,9 @@ public AtomicSerializationTests(IntegrationTestContext diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicTraceLoggingTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicTraceLoggingTests.cs index f3c47ed4b5..6eb2ce3a37 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicTraceLoggingTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/AtomicTraceLoggingTests.cs @@ -19,36 +19,35 @@ public AtomicTraceLoggingTests(IntegrationTestContext(); - var loggerFactory = new FakeLoggerFactory(LogLevel.Trace); - testContext.ConfigureLogging(options => { - options.ClearProviders(); - options.AddProvider(loggerFactory); + var loggerProvider = new CapturingLoggerProvider((category, level) => + level >= LogLevel.Trace && category.StartsWith("JsonApiDotNetCore.", StringComparison.Ordinal)); + + options.AddProvider(loggerProvider); options.SetMinimumLevel(LogLevel.Trace); - options.AddFilter((category, _) => category != null && category.StartsWith("JsonApiDotNetCore.", StringComparison.Ordinal)); - }); - testContext.ConfigureServices(services => services.AddSingleton(loggerFactory)); + options.Services.AddSingleton(loggerProvider); + }); } [Fact] public async Task Logs_execution_flow_at_Trace_level_on_operations_request() { // Arrange - var loggerFactory = _testContext.Factory.Services.GetRequiredService(); - loggerFactory.Logger.Clear(); + var loggerProvider = _testContext.Factory.Services.GetRequiredService(); + loggerProvider.Clear(); - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Lyric = _fakers.Lyric.Generate(); - existingTrack.OwnedBy = _fakers.RecordCompany.Generate(); - existingTrack.Performers = _fakers.Performer.Generate(1); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Lyric = _fakers.Lyric.GenerateOne(); + existingTrack.OwnedBy = _fakers.RecordCompany.GenerateOne(); + existingTrack.Performers = _fakers.Performer.GenerateList(1); - string newGenre = _fakers.MusicTrack.Generate().Genre!; + string newGenre = _fakers.MusicTrack.GenerateOne().Genre!; - Lyric existingLyric = _fakers.Lyric.Generate(); - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); - Performer existingPerformer = _fakers.Performer.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); + Performer existingPerformer = _fakers.Performer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -116,7 +115,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Should().BeEmpty(); - IReadOnlyList logLines = loggerFactory.Logger.GetLines(); + IReadOnlyList logLines = loggerProvider.GetLines(); logLines.Should().BeEquivalentTo(new[] { @@ -201,7 +200,8 @@ [TRACE] Entering PostOperationsAsync(operations: [ "PrimaryResourceType": "musicTracks", "IsCollection": false, "IsReadOnly": false, - "WriteOperation": "UpdateResource" + "WriteOperation": "UpdateResource", + "Extensions": [] } } ]) diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/MaximumOperationsPerRequestTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/MaximumOperationsPerRequestTests.cs index f24e25a216..b18c4991db 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/MaximumOperationsPerRequestTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Mixed/MaximumOperationsPerRequestTests.cs @@ -65,15 +65,15 @@ public async Task Cannot_process_more_operations_than_maximum() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Too many operations in request."); error.Detail.Should().Be("The number of operations in this request (3) is higher than the maximum of 2."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ModelStateValidation/AtomicModelStateValidationTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ModelStateValidation/AtomicModelStateValidationTests.cs index 1d095377bd..18e7640d22 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ModelStateValidation/AtomicModelStateValidationTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ModelStateValidation/AtomicModelStateValidationTests.cs @@ -17,8 +17,6 @@ public AtomicModelStateValidationTests(IntegrationTestContext services.AddSingleton()); - testContext.UseController(); } @@ -53,20 +51,20 @@ public async Task Cannot_create_resource_with_multiple_violations() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(2); + responseDocument.Errors.Should().HaveCount(2); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error1.Title.Should().Be("Input validation failed."); error1.Detail.Should().Be("The Title field is required."); - error1.Source.ShouldNotBeNull(); + error1.Source.Should().NotBeNull(); error1.Source.Pointer.Should().Be("/atomic:operations[0]/data/attributes/title"); ErrorObject error2 = responseDocument.Errors[1]; error2.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error2.Title.Should().Be("Input validation failed."); error2.Detail.Should().Be("The field LengthInSeconds must be between 1 and 1440."); - error2.Source.ShouldNotBeNull(); + error2.Source.Should().NotBeNull(); error2.Source.Pointer.Should().Be("/atomic:operations[0]/data/attributes/lengthInSeconds"); } @@ -74,7 +72,8 @@ public async Task Cannot_create_resource_with_multiple_violations() public async Task Cannot_create_resource_when_violation_from_custom_ValidationAttribute() { // Arrange - var clock = _testContext.Factory.Services.GetRequiredService(); + var timeProvider = _testContext.Factory.Services.GetRequiredService(); + DateTimeOffset utcNow = timeProvider.GetUtcNow(); var requestBody = new { @@ -90,7 +89,7 @@ public async Task Cannot_create_resource_when_violation_from_custom_ValidationAt { title = "some", lengthInSeconds = 120, - releasedAt = clock.UtcNow.AddDays(1) + releasedAt = utcNow.AddDays(1) } } } @@ -105,13 +104,13 @@ public async Task Cannot_create_resource_when_violation_from_custom_ValidationAt // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Input validation failed."); error.Detail.Should().Be("ReleasedAt must be in the past."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/attributes/releasedAt"); } @@ -119,8 +118,8 @@ public async Task Cannot_create_resource_when_violation_from_custom_ValidationAt public async Task Can_create_resource_with_annotated_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - string newPlaylistName = _fakers.Playlist.Generate().Name; + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + string newPlaylistName = _fakers.Playlist.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -169,15 +168,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(1); + responseDocument.Results.Should().HaveCount(1); - long newPlaylistId = long.Parse(responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().Id.ShouldNotBeNull()); + long newPlaylistId = long.Parse(responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { Playlist playlistInDatabase = await dbContext.Playlists.Include(playlist => playlist.Tracks).FirstWithIdAsync(newPlaylistId); - playlistInDatabase.Tracks.ShouldHaveCount(1); + playlistInDatabase.Tracks.Should().HaveCount(1); playlistInDatabase.Tracks[0].Id.Should().Be(existingTrack.Id); }); } @@ -186,7 +185,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_multiple_violations() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -223,20 +222,20 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(2); + responseDocument.Errors.Should().HaveCount(2); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error1.Title.Should().Be("Input validation failed."); error1.Detail.Should().Be("The Title field is required."); - error1.Source.ShouldNotBeNull(); + error1.Source.Should().NotBeNull(); error1.Source.Pointer.Should().Be("/atomic:operations[0]/data/attributes/title"); ErrorObject error2 = responseDocument.Errors[1]; error2.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error2.Title.Should().Be("Input validation failed."); error2.Detail.Should().Be("The field LengthInSeconds must be between 1 and 1440."); - error2.Source.ShouldNotBeNull(); + error2.Source.Should().NotBeNull(); error2.Source.Pointer.Should().Be("/atomic:operations[0]/data/attributes/lengthInSeconds"); } @@ -244,8 +243,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_omitted_required_attribute() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - string newTrackGenre = _fakers.MusicTrack.Generate().Genre!; + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + string newTrackGenre = _fakers.MusicTrack.GenerateOne().Genre!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -296,8 +295,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_annotated_relationship() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -349,7 +348,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Playlist playlistInDatabase = await dbContext.Playlists.Include(playlist => playlist.Tracks).FirstWithIdAsync(existingPlaylist.Id); - playlistInDatabase.Tracks.ShouldHaveCount(1); + playlistInDatabase.Tracks.Should().HaveCount(1); playlistInDatabase.Tracks[0].Id.Should().Be(existingTrack.Id); }); } @@ -358,8 +357,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_ManyToOne_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -403,7 +402,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { MusicTrack trackInDatabase = await dbContext.MusicTracks.Include(musicTrack => musicTrack.OwnedBy).FirstWithIdAsync(existingTrack.Id); - trackInDatabase.OwnedBy.ShouldNotBeNull(); + trackInDatabase.OwnedBy.Should().NotBeNull(); trackInDatabase.OwnedBy.Id.Should().Be(existingCompany.Id); }); } @@ -412,8 +411,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_ManyToMany_relationship() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -460,7 +459,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Playlist playlistInDatabase = await dbContext.Playlists.Include(playlist => playlist.Tracks).FirstWithIdAsync(existingPlaylist.Id); - playlistInDatabase.Tracks.ShouldHaveCount(1); + playlistInDatabase.Tracks.Should().HaveCount(1); playlistInDatabase.Tracks[0].Id.Should().Be(existingTrack.Id); }); } @@ -510,20 +509,20 @@ public async Task Validates_all_operations_before_execution_starts() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(2); + responseDocument.Errors.Should().HaveCount(2); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error1.Title.Should().Be("Input validation failed."); error1.Detail.Should().Be("The Name field is required."); - error1.Source.ShouldNotBeNull(); + error1.Source.Should().NotBeNull(); error1.Source.Pointer.Should().Be("/atomic:operations[0]/data/attributes/name"); ErrorObject error2 = responseDocument.Errors[1]; error2.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error2.Title.Should().Be("Input validation failed."); error2.Detail.Should().Be("The field LengthInSeconds must be between 1 and 1440."); - error2.Source.ShouldNotBeNull(); + error2.Source.Should().NotBeNull(); error2.Source.Pointer.Should().Be("/atomic:operations[1]/data/attributes/lengthInSeconds"); } @@ -594,7 +593,7 @@ public async Task Does_not_exceed_MaxModelValidationErrors() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(3); + responseDocument.Errors.Should().HaveCount(3); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); @@ -606,14 +605,14 @@ public async Task Does_not_exceed_MaxModelValidationErrors() error2.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error2.Title.Should().Be("Input validation failed."); error2.Detail.Should().Be("The Name field is required."); - error2.Source.ShouldNotBeNull(); + error2.Source.Should().NotBeNull(); error2.Source.Pointer.Should().Be("/atomic:operations[0]/data/attributes/name"); ErrorObject error3 = responseDocument.Errors[2]; error3.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error3.Title.Should().Be("Input validation failed."); error3.Detail.Should().Be("The Name field is required."); - error3.Source.ShouldNotBeNull(); + error3.Source.Should().NotBeNull(); error3.Source.Pointer.Should().Be("/atomic:operations[1]/data/attributes/name"); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/OperationsController.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/OperationsController.cs index 78426804b3..2ea1b88bad 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/OperationsController.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/OperationsController.cs @@ -9,5 +9,5 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.AtomicOperations; public sealed class OperationsController( IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, IOperationsProcessor processor, IJsonApiRequest request, - ITargetedFields targetedFields, IAtomicOperationFilter operationFilter) : JsonApiOperationsController(options, resourceGraph, loggerFactory, processor, - request, targetedFields, operationFilter); + ITargetedFields targetedFields, IAtomicOperationFilter operationFilter) + : JsonApiOperationsController(options, resourceGraph, loggerFactory, processor, request, targetedFields, operationFilter); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/OperationsDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/OperationsDbContext.cs index e4e22195a8..e13a922941 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/OperationsDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/OperationsDbContext.cs @@ -7,7 +7,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.AtomicOperations; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class OperationsDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class OperationsDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet Playlists => Set(); public DbSet MusicTracks => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/OperationsFakers.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/OperationsFakers.cs index b66fa6d5df..f09dfbdf0a 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/OperationsFakers.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/OperationsFakers.cs @@ -9,7 +9,7 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.AtomicOperations; internal sealed class OperationsFakers { - private static readonly Lazy> LazyLanguageIsoCodes = new(() => CultureInfo + private static readonly Lazy LazyLanguageIsoCodes = new(() => CultureInfo .GetCultures(CultureTypes.NeutralCultures) .Where(culture => !string.IsNullOrEmpty(culture.Name)) .Select(culture => culture.Name) @@ -33,7 +33,7 @@ internal sealed class OperationsFakers private readonly Lazy> _lazyTextLanguageFaker = new(() => new Faker() .MakeDeterministic() - .RuleFor(textLanguage => textLanguage.IsoCode, faker => faker.PickRandom(LazyLanguageIsoCodes.Value))); + .RuleFor(textLanguage => textLanguage.IsoCode, faker => faker.PickRandom(LazyLanguageIsoCodes.Value))); private readonly Lazy> _lazyPerformerFaker = new(() => new Faker() .MakeDeterministic() diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/QueryStrings/AtomicQueryStringTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/QueryStrings/AtomicQueryStringTests.cs index 6db0926773..a635e12fb6 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/QueryStrings/AtomicQueryStringTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/QueryStrings/AtomicQueryStringTests.cs @@ -20,12 +20,7 @@ public AtomicQueryStringTests(IntegrationTestContext(); testContext.UseController(); - testContext.ConfigureServices(services => - { - services.AddResourceDefinition(); - - services.AddSingleton(); - }); + testContext.ConfigureServices(services => services.AddResourceDefinition()); } [Fact] @@ -58,13 +53,13 @@ public async Task Cannot_include_at_operations_endpoint() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Usage of one or more query string parameters is not allowed at the requested endpoint."); error.Detail.Should().Be("The parameter 'include' cannot be used at this endpoint."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("include"); } @@ -98,13 +93,13 @@ public async Task Cannot_filter_at_operations_endpoint() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Usage of one or more query string parameters is not allowed at the requested endpoint."); error.Detail.Should().Be("The parameter 'filter' cannot be used at this endpoint."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("filter"); } @@ -138,13 +133,13 @@ public async Task Cannot_sort_at_operations_endpoint() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Usage of one or more query string parameters is not allowed at the requested endpoint."); error.Detail.Should().Be("The parameter 'sort' cannot be used at this endpoint."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("sort"); } @@ -178,13 +173,13 @@ public async Task Cannot_use_pagination_number_at_operations_endpoint() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Usage of one or more query string parameters is not allowed at the requested endpoint."); error.Detail.Should().Be("The parameter 'page[number]' cannot be used at this endpoint."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("page[number]"); } @@ -218,13 +213,13 @@ public async Task Cannot_use_pagination_size_at_operations_endpoint() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Usage of one or more query string parameters is not allowed at the requested endpoint."); error.Detail.Should().Be("The parameter 'page[size]' cannot be used at this endpoint."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("page[size]"); } @@ -258,13 +253,13 @@ public async Task Cannot_use_sparse_fieldset_at_operations_endpoint() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Usage of one or more query string parameters is not allowed at the requested endpoint."); error.Detail.Should().Be("The parameter 'fields[recordCompanies]' cannot be used at this endpoint."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("fields[recordCompanies]"); } @@ -272,12 +267,13 @@ public async Task Cannot_use_sparse_fieldset_at_operations_endpoint() public async Task Can_use_Queryable_handler_at_resource_endpoint() { // Arrange - var clock = _testContext.Factory.Services.GetRequiredService(); + var timeProvider = _testContext.Factory.Services.GetRequiredService(); + DateTimeOffset utcNow = timeProvider.GetUtcNow(); - List musicTracks = _fakers.MusicTrack.Generate(3); - musicTracks[0].ReleasedAt = clock.UtcNow.AddMonths(5); - musicTracks[1].ReleasedAt = clock.UtcNow.AddMonths(-5); - musicTracks[2].ReleasedAt = clock.UtcNow.AddMonths(-1); + List musicTracks = _fakers.MusicTrack.GenerateList(3); + musicTracks[0].ReleasedAt = utcNow.AddMonths(5); + musicTracks[1].ReleasedAt = utcNow.AddMonths(-5); + musicTracks[2].ReleasedAt = utcNow.AddMonths(-1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -294,7 +290,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(musicTracks[2].StringId); } @@ -302,7 +298,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_use_Queryable_handler_at_operations_endpoint() { // Arrange - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; var requestBody = new { @@ -331,7 +327,7 @@ public async Task Cannot_use_Queryable_handler_at_operations_endpoint() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); @@ -340,7 +336,7 @@ public async Task Cannot_use_Queryable_handler_at_operations_endpoint() error.Detail.Should().Be("Query string parameter 'isRecentlyReleased' is unknown. " + "Set 'AllowUnknownQueryStringParameters' to 'true' in options to ignore unknown parameters."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("isRecentlyReleased"); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/QueryStrings/MusicTrackReleaseDefinition.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/QueryStrings/MusicTrackReleaseDefinition.cs index 84827322ad..b72b3eb3d2 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/QueryStrings/MusicTrackReleaseDefinition.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/QueryStrings/MusicTrackReleaseDefinition.cs @@ -1,23 +1,21 @@ using JetBrains.Annotations; -using JsonApiDotNetCore; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Resources; using Microsoft.Extensions.Primitives; -using TestBuildingBlocks; namespace JsonApiDotNetCoreTests.IntegrationTests.AtomicOperations.QueryStrings; [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] public sealed class MusicTrackReleaseDefinition : JsonApiResourceDefinition { - private readonly ISystemClock _systemClock; + private readonly TimeProvider _timeProvider; - public MusicTrackReleaseDefinition(IResourceGraph resourceGraph, ISystemClock systemClock) + public MusicTrackReleaseDefinition(IResourceGraph resourceGraph, TimeProvider timeProvider) : base(resourceGraph) { - ArgumentGuard.NotNull(systemClock); + ArgumentNullException.ThrowIfNull(timeProvider); - _systemClock = systemClock; + _timeProvider = timeProvider; } public override QueryStringParameterHandlers OnRegisterQueryableHandlersForQueryStringParameters() @@ -34,7 +32,8 @@ private IQueryable FilterOnRecentlyReleased(IQueryable s if (bool.Parse(parameterValue.ToString())) { - tracks = tracks.Where(musicTrack => musicTrack.ReleasedAt < _systemClock.UtcNow && musicTrack.ReleasedAt > _systemClock.UtcNow.AddMonths(-3)); + DateTimeOffset utcNow = _timeProvider.GetUtcNow(); + tracks = tracks.Where(musicTrack => musicTrack.ReleasedAt < utcNow && musicTrack.ReleasedAt > utcNow.AddMonths(-3)); } return tracks; diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ResourceDefinitions/Serialization/AtomicSerializationResourceDefinitionTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ResourceDefinitions/Serialization/AtomicSerializationResourceDefinitionTests.cs index 4e2fa4f937..cb0325882e 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ResourceDefinitions/Serialization/AtomicSerializationResourceDefinitionTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ResourceDefinitions/Serialization/AtomicSerializationResourceDefinitionTests.cs @@ -40,7 +40,7 @@ public async Task Transforms_on_create_resource_with_side_effects() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - List newCompanies = _fakers.RecordCompany.Generate(2); + List newCompanies = _fakers.RecordCompany.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -88,28 +88,28 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(2); + responseDocument.Results.Should().HaveCount(2); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { - resource.Attributes.ShouldContainKey("name").With(value => value.Should().Be(newCompanies[0].Name.ToUpperInvariant())); + resource.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(newCompanies[0].Name.ToUpperInvariant()); string countryOfResidence = newCompanies[0].CountryOfResidence!.ToUpperInvariant(); - resource.Attributes.ShouldContainKey("countryOfResidence").With(value => value.Should().Be(countryOfResidence)); + resource.Attributes.Should().ContainKey("countryOfResidence").WhoseValue.Should().Be(countryOfResidence); }); - responseDocument.Results[1].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[1].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { - resource.Attributes.ShouldContainKey("name").With(value => value.Should().Be(newCompanies[1].Name.ToUpperInvariant())); + resource.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(newCompanies[1].Name.ToUpperInvariant()); string countryOfResidence = newCompanies[1].CountryOfResidence!.ToUpperInvariant(); - resource.Attributes.ShouldContainKey("countryOfResidence").With(value => value.Should().Be(countryOfResidence)); + resource.Attributes.Should().ContainKey("countryOfResidence").WhoseValue.Should().Be(countryOfResidence); }); await _testContext.RunOnDatabaseAsync(async dbContext => { List companiesInDatabase = await dbContext.RecordCompanies.ToListAsync(); - companiesInDatabase.ShouldHaveCount(2); + companiesInDatabase.Should().HaveCount(2); companiesInDatabase[0].Name.Should().Be(newCompanies[0].Name.ToUpperInvariant()); companiesInDatabase[0].CountryOfResidence.Should().Be(newCompanies[0].CountryOfResidence); @@ -133,9 +133,9 @@ public async Task Skips_on_create_resource_with_ToOne_relationship() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -181,7 +181,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(1); + responseDocument.Results.Should().HaveCount(1); hitCounter.HitExtensibilityPoints.Should().BeEmpty(); } @@ -192,7 +192,7 @@ public async Task Transforms_on_update_resource_with_side_effects() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - List existingCompanies = _fakers.RecordCompany.Generate(2); + List existingCompanies = _fakers.RecordCompany.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -240,28 +240,28 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(2); + responseDocument.Results.Should().HaveCount(2); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { - resource.Attributes.ShouldContainKey("name").With(value => value.Should().Be(existingCompanies[0].Name)); + resource.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(existingCompanies[0].Name); string countryOfResidence = existingCompanies[0].CountryOfResidence!.ToUpperInvariant(); - resource.Attributes.ShouldContainKey("countryOfResidence").With(value => value.Should().Be(countryOfResidence)); + resource.Attributes.Should().ContainKey("countryOfResidence").WhoseValue.Should().Be(countryOfResidence); }); - responseDocument.Results[1].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[1].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { - resource.Attributes.ShouldContainKey("name").With(value => value.Should().Be(existingCompanies[1].Name)); + resource.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(existingCompanies[1].Name); string countryOfResidence = existingCompanies[1].CountryOfResidence!.ToUpperInvariant(); - resource.Attributes.ShouldContainKey("countryOfResidence").With(value => value.Should().Be(countryOfResidence)); + resource.Attributes.Should().ContainKey("countryOfResidence").WhoseValue.Should().Be(countryOfResidence); }); await _testContext.RunOnDatabaseAsync(async dbContext => { List companiesInDatabase = await dbContext.RecordCompanies.ToListAsync(); - companiesInDatabase.ShouldHaveCount(2); + companiesInDatabase.Should().HaveCount(2); companiesInDatabase[0].Name.Should().Be(existingCompanies[0].Name); companiesInDatabase[0].CountryOfResidence.Should().Be(existingCompanies[0].CountryOfResidence); @@ -285,8 +285,8 @@ public async Task Skips_on_update_resource_with_ToOne_relationship() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -332,7 +332,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(1); + responseDocument.Results.Should().HaveCount(1); hitCounter.HitExtensibilityPoints.Should().BeEmpty(); } @@ -343,8 +343,8 @@ public async Task Skips_on_update_ToOne_relationship() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ResourceDefinitions/SparseFieldSets/AtomicSparseFieldSetResourceDefinitionTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ResourceDefinitions/SparseFieldSets/AtomicSparseFieldSetResourceDefinitionTests.cs index 63fb7e8eb2..9263d1ec32 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ResourceDefinitions/SparseFieldSets/AtomicSparseFieldSetResourceDefinitionTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/ResourceDefinitions/SparseFieldSets/AtomicSparseFieldSetResourceDefinitionTests.cs @@ -43,7 +43,7 @@ public async Task Hides_text_in_create_resource_with_side_effects() var provider = _testContext.Factory.Services.GetRequiredService(); provider.CanViewText = false; - List newLyrics = _fakers.Lyric.Generate(2); + List newLyrics = _fakers.Lyric.GenerateList(2); var requestBody = new { @@ -86,17 +86,17 @@ public async Task Hides_text_in_create_resource_with_side_effects() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(2); + responseDocument.Results.Should().HaveCount(2); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { - resource.Attributes.ShouldContainKey("format").With(value => value.Should().Be(newLyrics[0].Format)); + resource.Attributes.Should().ContainKey("format").WhoseValue.Should().Be(newLyrics[0].Format); resource.Attributes.Should().NotContainKey("text"); }); - responseDocument.Results[1].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[1].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { - resource.Attributes.ShouldContainKey("format").With(value => value.Should().Be(newLyrics[1].Format)); + resource.Attributes.Should().ContainKey("format").WhoseValue.Should().Be(newLyrics[1].Format); resource.Attributes.Should().NotContainKey("text"); }); @@ -118,7 +118,7 @@ public async Task Hides_text_in_update_resource_with_side_effects() var provider = _testContext.Factory.Services.GetRequiredService(); provider.CanViewText = false; - List existingLyrics = _fakers.Lyric.Generate(2); + List existingLyrics = _fakers.Lyric.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -165,17 +165,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(2); + responseDocument.Results.Should().HaveCount(2); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { - resource.Attributes.ShouldContainKey("format").With(value => value.Should().Be(existingLyrics[0].Format)); + resource.Attributes.Should().ContainKey("format").WhoseValue.Should().Be(existingLyrics[0].Format); resource.Attributes.Should().NotContainKey("text"); }); - responseDocument.Results[1].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[1].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { - resource.Attributes.ShouldContainKey("format").With(value => value.Should().Be(existingLyrics[1].Format)); + resource.Attributes.Should().ContainKey("format").WhoseValue.Should().Be(existingLyrics[1].Format); resource.Attributes.Should().NotContainKey("text"); }); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/AtomicRollbackTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/AtomicRollbackTests.cs index 82646686d4..f27e6c4a93 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/AtomicRollbackTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/AtomicRollbackTests.cs @@ -23,9 +23,9 @@ public AtomicRollbackTests(IntegrationTestContext { @@ -88,13 +88,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); error.Title.Should().Be("A related resource does not exist."); error.Detail.Should().Be($"Related resource of type 'performers' with ID '{unknownPerformerId}' in relationship 'performers' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[1]"); await _testContext.RunOnDatabaseAsync(async dbContext => @@ -111,7 +111,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_restore_to_previous_savepoint_on_error() { // Arrange - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -168,13 +168,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); error.Title.Should().Be("A related resource does not exist."); error.Detail.Should().Be($"Related resource of type 'performers' with ID '{unknownPerformerId}' in relationship 'performers' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[1]"); await _testContext.RunOnDatabaseAsync(async dbContext => diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/AtomicTransactionConsistencyTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/AtomicTransactionConsistencyTests.cs index 9c054c349b..14cfc466a0 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/AtomicTransactionConsistencyTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/AtomicTransactionConsistencyTests.cs @@ -64,13 +64,13 @@ public async Task Cannot_use_non_transactional_repository() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Unsupported resource type in atomic:operations request."); error.Detail.Should().Be("Operations on resources of type 'performers' cannot be used because transaction support is unavailable."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); } @@ -78,7 +78,7 @@ public async Task Cannot_use_non_transactional_repository() public async Task Cannot_use_transactional_repository_without_active_transaction() { // Arrange - string newTrackTitle = _fakers.MusicTrack.Generate().Title; + string newTrackTitle = _fakers.MusicTrack.GenerateOne().Title; var requestBody = new { @@ -107,13 +107,13 @@ public async Task Cannot_use_transactional_repository_without_active_transaction // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Unsupported combination of resource types in atomic:operations request."); error.Detail.Should().Be("All operations need to participate in a single shared transaction, which is not the case for this request."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); } @@ -121,7 +121,7 @@ public async Task Cannot_use_transactional_repository_without_active_transaction public async Task Cannot_use_distributed_transaction() { // Arrange - string newLyricText = _fakers.Lyric.Generate().Text; + string newLyricText = _fakers.Lyric.GenerateOne().Text; var requestBody = new { @@ -150,13 +150,13 @@ public async Task Cannot_use_distributed_transaction() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Unsupported combination of resource types in atomic:operations request."); error.Detail.Should().Be("All operations need to participate in a single shared transaction, which is not the case for this request."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/ExtraDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/ExtraDbContext.cs index efc9ebaeaa..290efd3437 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/ExtraDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Transactions/ExtraDbContext.cs @@ -5,4 +5,5 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.AtomicOperations.Transactions; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class ExtraDbContext(DbContextOptions options) : TestableDbContext(options); +public sealed class ExtraDbContext(DbContextOptions options) + : TestableDbContext(options); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicAddToToManyRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicAddToToManyRelationshipTests.cs index 293b4b495c..419c8e5b16 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicAddToToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicAddToToManyRelationshipTests.cs @@ -23,8 +23,8 @@ public AtomicAddToToManyRelationshipTests(IntegrationTestContext { @@ -62,25 +62,25 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); error.Title.Should().Be("Failed to deserialize request body: Only to-many relationships can be targeted through this operation."); error.Detail.Should().Be("Relationship 'ownedBy' is not a to-many relationship."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref/relationship"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_add_to_OneToMany_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Performers = _fakers.Performer.Generate(1); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Performers = _fakers.Performer.GenerateList(1); - List existingPerformers = _fakers.Performer.Generate(2); + List existingPerformers = _fakers.Performer.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -146,7 +146,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { MusicTrack trackInDatabase = await dbContext.MusicTracks.Include(musicTrack => musicTrack.Performers).FirstWithIdAsync(existingTrack.Id); - trackInDatabase.Performers.ShouldHaveCount(3); + trackInDatabase.Performers.Should().HaveCount(3); trackInDatabase.Performers.Should().ContainSingle(performer => performer.Id == existingTrack.Performers[0].Id); trackInDatabase.Performers.Should().ContainSingle(performer => performer.Id == existingPerformers[0].Id); trackInDatabase.Performers.Should().ContainSingle(performer => performer.Id == existingPerformers[1].Id); @@ -157,10 +157,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_to_ManyToMany_relationship() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); - existingPlaylist.Tracks = _fakers.MusicTrack.Generate(1); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); + existingPlaylist.Tracks = _fakers.MusicTrack.GenerateList(1); - List existingTracks = _fakers.MusicTrack.Generate(2); + List existingTracks = _fakers.MusicTrack.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -226,7 +226,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Playlist playlistInDatabase = await dbContext.Playlists.Include(playlist => playlist.Tracks).FirstWithIdAsync(existingPlaylist.Id); - playlistInDatabase.Tracks.ShouldHaveCount(3); + playlistInDatabase.Tracks.Should().HaveCount(3); playlistInDatabase.Tracks.Should().ContainSingle(musicTrack => musicTrack.Id == existingPlaylist.Tracks[0].Id); playlistInDatabase.Tracks.Should().ContainSingle(musicTrack => musicTrack.Id == existingTracks[0].Id); playlistInDatabase.Tracks.Should().ContainSingle(musicTrack => musicTrack.Id == existingTracks[1].Id); @@ -257,15 +257,15 @@ public async Task Cannot_add_for_href_element() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'href' element is not supported."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/href"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -296,15 +296,15 @@ public async Task Cannot_add_for_missing_type_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -336,15 +336,15 @@ public async Task Cannot_add_for_unknown_type_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -375,22 +375,22 @@ public async Task Cannot_add_for_missing_ID_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' or 'lid' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_add_for_unknown_ID_in_ref() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -433,13 +433,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); error.Title.Should().Be("The requested resource does not exist."); error.Detail.Should().Be($"Resource of type 'recordCompanies' with ID '{companyId}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); error.Meta.Should().NotContainKey("requestBody"); } @@ -474,15 +474,15 @@ public async Task Cannot_add_for_ID_and_local_ID_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' and 'lid' element are mutually exclusive."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -513,15 +513,15 @@ public async Task Cannot_add_for_missing_relationship_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'relationship' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -553,22 +553,22 @@ public async Task Cannot_add_for_unknown_relationship_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown relationship found."); error.Detail.Should().Be($"Relationship '{Unknown.Relationship}' does not exist on resource type 'performers'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref/relationship"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_add_for_missing_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -601,22 +601,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'data' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_add_for_null_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -650,22 +650,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an array, instead of 'null'."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_add_for_object_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -701,15 +701,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an array, instead of an object."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -748,15 +748,15 @@ public async Task Cannot_add_for_missing_type_in_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -796,15 +796,15 @@ public async Task Cannot_add_for_unknown_type_in_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data[0]/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -843,15 +843,15 @@ public async Task Cannot_add_for_missing_ID_in_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' or 'lid' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -892,22 +892,22 @@ public async Task Cannot_add_for_ID_and_local_ID_in_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' and 'lid' element are mutually exclusive."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_add_for_unknown_IDs_in_data() { // Arrange - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); string[] trackIds = [ @@ -959,20 +959,20 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(2); + responseDocument.Errors.Should().HaveCount(2); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.NotFound); error1.Title.Should().Be("A related resource does not exist."); error1.Detail.Should().Be($"Related resource of type 'musicTracks' with ID '{trackIds[0]}' in relationship 'tracks' does not exist."); - error1.Source.ShouldNotBeNull(); + error1.Source.Should().NotBeNull(); error1.Source.Pointer.Should().Be("/atomic:operations[0]"); ErrorObject error2 = responseDocument.Errors[1]; error2.StatusCode.Should().Be(HttpStatusCode.NotFound); error2.Title.Should().Be("A related resource does not exist."); error2.Detail.Should().Be($"Related resource of type 'musicTracks' with ID '{trackIds[1]}' in relationship 'tracks' does not exist."); - error2.Source.ShouldNotBeNull(); + error2.Source.Should().NotBeNull(); error2.Source.Pointer.Should().Be("/atomic:operations[0]"); } @@ -980,7 +980,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_for_relationship_mismatch_between_ref_and_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1021,23 +1021,23 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Incompatible resource type found."); error.Detail.Should().Be("Type 'playlists' is not convertible to type 'performers' of relationship 'performers'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data[0]/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_add_with_empty_data_array() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Performers = _fakers.Performer.Generate(1); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Performers = _fakers.Performer.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1077,7 +1077,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { MusicTrack trackInDatabase = await dbContext.MusicTracks.Include(musicTrack => musicTrack.Performers).FirstWithIdAsync(existingTrack.Id); - trackInDatabase.Performers.ShouldHaveCount(1); + trackInDatabase.Performers.Should().HaveCount(1); trackInDatabase.Performers[0].Id.Should().Be(existingTrack.Performers[0].Id); }); } @@ -1086,7 +1086,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_with_blocked_capability() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1124,14 +1124,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Relationship cannot be added to."); error.Detail.Should().Be("The relationship 'occursIn' on resource type 'musicTracks' cannot be added to."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref/relationship"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicRemoveFromToManyRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicRemoveFromToManyRelationshipTests.cs index 7e9654ab30..98d954c910 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicRemoveFromToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicRemoveFromToManyRelationshipTests.cs @@ -23,8 +23,8 @@ public AtomicRemoveFromToManyRelationshipTests(IntegrationTestContext { @@ -62,23 +62,23 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); error.Title.Should().Be("Failed to deserialize request body: Only to-many relationships can be targeted through this operation."); error.Detail.Should().Be("Relationship 'ownedBy' is not a to-many relationship."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref/relationship"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_remove_from_OneToMany_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Performers = _fakers.Performer.Generate(3); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Performers = _fakers.Performer.GenerateList(3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -144,11 +144,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { MusicTrack trackInDatabase = await dbContext.MusicTracks.Include(musicTrack => musicTrack.Performers).FirstWithIdAsync(existingTrack.Id); - trackInDatabase.Performers.ShouldHaveCount(1); + trackInDatabase.Performers.Should().HaveCount(1); trackInDatabase.Performers[0].Id.Should().Be(existingTrack.Performers[1].Id); List performersInDatabase = await dbContext.Performers.ToListAsync(); - performersInDatabase.ShouldHaveCount(3); + performersInDatabase.Should().HaveCount(3); }); } @@ -156,8 +156,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_ManyToMany_relationship() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); - existingPlaylist.Tracks = _fakers.MusicTrack.Generate(3); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); + existingPlaylist.Tracks = _fakers.MusicTrack.GenerateList(3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -223,12 +223,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Playlist playlistInDatabase = await dbContext.Playlists.Include(playlist => playlist.Tracks).FirstWithIdAsync(existingPlaylist.Id); - playlistInDatabase.Tracks.ShouldHaveCount(1); + playlistInDatabase.Tracks.Should().HaveCount(1); playlistInDatabase.Tracks[0].Id.Should().Be(existingPlaylist.Tracks[1].Id); List tracksInDatabase = await dbContext.MusicTracks.ToListAsync(); - tracksInDatabase.ShouldHaveCount(3); + tracksInDatabase.Should().HaveCount(3); }); } @@ -256,15 +256,15 @@ public async Task Cannot_remove_for_href_element() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'href' element is not supported."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/href"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -295,15 +295,15 @@ public async Task Cannot_remove_for_missing_type_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -335,15 +335,15 @@ public async Task Cannot_remove_for_unknown_type_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -374,22 +374,22 @@ public async Task Cannot_remove_for_missing_ID_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' or 'lid' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_remove_for_unknown_ID_in_ref() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -432,13 +432,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); error.Title.Should().Be("The requested resource does not exist."); error.Detail.Should().Be($"Resource of type 'recordCompanies' with ID '{companyId}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); error.Meta.Should().NotContainKey("requestBody"); } @@ -473,15 +473,15 @@ public async Task Cannot_remove_for_ID_and_local_ID_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' and 'lid' element are mutually exclusive."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -513,22 +513,22 @@ public async Task Cannot_remove_for_unknown_relationship_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown relationship found."); error.Detail.Should().Be($"Relationship '{Unknown.Relationship}' does not exist on resource type 'performers'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref/relationship"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_remove_for_missing_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -561,22 +561,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'data' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_remove_for_null_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -610,22 +610,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an array, instead of 'null'."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_remove_for_object_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -661,15 +661,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an array, instead of an object."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -708,15 +708,15 @@ public async Task Cannot_remove_for_missing_type_in_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -756,15 +756,15 @@ public async Task Cannot_remove_for_unknown_type_in_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data[0]/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -803,15 +803,15 @@ public async Task Cannot_remove_for_missing_ID_in_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' or 'lid' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -852,22 +852,22 @@ public async Task Cannot_remove_for_ID_and_local_ID_in_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' and 'lid' element are mutually exclusive."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_remove_for_unknown_IDs_in_data() { // Arrange - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); string[] trackIds = [ @@ -919,20 +919,20 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(2); + responseDocument.Errors.Should().HaveCount(2); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.NotFound); error1.Title.Should().Be("A related resource does not exist."); error1.Detail.Should().Be($"Related resource of type 'musicTracks' with ID '{trackIds[0]}' in relationship 'tracks' does not exist."); - error1.Source.ShouldNotBeNull(); + error1.Source.Should().NotBeNull(); error1.Source.Pointer.Should().Be("/atomic:operations[0]"); ErrorObject error2 = responseDocument.Errors[1]; error2.StatusCode.Should().Be(HttpStatusCode.NotFound); error2.Title.Should().Be("A related resource does not exist."); error2.Detail.Should().Be($"Related resource of type 'musicTracks' with ID '{trackIds[1]}' in relationship 'tracks' does not exist."); - error2.Source.ShouldNotBeNull(); + error2.Source.Should().NotBeNull(); error2.Source.Pointer.Should().Be("/atomic:operations[0]"); } @@ -940,7 +940,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_for_relationship_mismatch_between_ref_and_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -981,23 +981,23 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Incompatible resource type found."); error.Detail.Should().Be("Type 'playlists' is not convertible to type 'performers' of relationship 'performers'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data[0]/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_remove_with_empty_data_array() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Performers = _fakers.Performer.Generate(1); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Performers = _fakers.Performer.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1038,7 +1038,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { MusicTrack trackInDatabase = await dbContext.MusicTracks.Include(musicTrack => musicTrack.Performers).FirstWithIdAsync(existingTrack.Id); - trackInDatabase.Performers.ShouldHaveCount(1); + trackInDatabase.Performers.Should().HaveCount(1); trackInDatabase.Performers[0].Id.Should().Be(existingTrack.Performers[0].Id); }); } @@ -1047,7 +1047,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_with_blocked_capability() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1085,14 +1085,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Relationship cannot be removed from."); error.Detail.Should().Be("The relationship 'occursIn' on resource type 'musicTracks' cannot be removed from."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref/relationship"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicReplaceToManyRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicReplaceToManyRelationshipTests.cs index bcedf104bf..3653763f60 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicReplaceToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicReplaceToManyRelationshipTests.cs @@ -23,8 +23,8 @@ public AtomicReplaceToManyRelationshipTests(IntegrationTestContext { @@ -68,7 +68,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => trackInDatabase.Performers.Should().BeEmpty(); List performersInDatabase = await dbContext.Performers.ToListAsync(); - performersInDatabase.ShouldHaveCount(2); + performersInDatabase.Should().HaveCount(2); }); } @@ -76,8 +76,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_ManyToMany_relationship() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); - existingPlaylist.Tracks = _fakers.MusicTrack.Generate(2); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); + existingPlaylist.Tracks = _fakers.MusicTrack.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -122,7 +122,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => List tracksInDatabase = await dbContext.MusicTracks.ToListAsync(); - tracksInDatabase.ShouldHaveCount(2); + tracksInDatabase.Should().HaveCount(2); }); } @@ -130,10 +130,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToMany_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Performers = _fakers.Performer.Generate(1); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Performers = _fakers.Performer.GenerateList(1); - List existingPerformers = _fakers.Performer.Generate(2); + List existingPerformers = _fakers.Performer.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -187,12 +187,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { MusicTrack trackInDatabase = await dbContext.MusicTracks.Include(musicTrack => musicTrack.Performers).FirstWithIdAsync(existingTrack.Id); - trackInDatabase.Performers.ShouldHaveCount(2); + trackInDatabase.Performers.Should().HaveCount(2); trackInDatabase.Performers.Should().ContainSingle(performer => performer.Id == existingPerformers[0].Id); trackInDatabase.Performers.Should().ContainSingle(performer => performer.Id == existingPerformers[1].Id); List performersInDatabase = await dbContext.Performers.ToListAsync(); - performersInDatabase.ShouldHaveCount(3); + performersInDatabase.Should().HaveCount(3); }); } @@ -200,10 +200,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ManyToMany_relationship() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); - existingPlaylist.Tracks = _fakers.MusicTrack.Generate(1); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); + existingPlaylist.Tracks = _fakers.MusicTrack.GenerateList(1); - List existingTracks = _fakers.MusicTrack.Generate(2); + List existingTracks = _fakers.MusicTrack.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -257,13 +257,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Playlist playlistInDatabase = await dbContext.Playlists.Include(playlist => playlist.Tracks).FirstWithIdAsync(existingPlaylist.Id); - playlistInDatabase.Tracks.ShouldHaveCount(2); + playlistInDatabase.Tracks.Should().HaveCount(2); playlistInDatabase.Tracks.Should().ContainSingle(musicTrack => musicTrack.Id == existingTracks[0].Id); playlistInDatabase.Tracks.Should().ContainSingle(musicTrack => musicTrack.Id == existingTracks[1].Id); List tracksInDatabase = await dbContext.MusicTracks.ToListAsync(); - tracksInDatabase.ShouldHaveCount(3); + tracksInDatabase.Should().HaveCount(3); }); } @@ -291,15 +291,15 @@ public async Task Cannot_replace_for_href_element() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'href' element is not supported."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/href"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -330,15 +330,15 @@ public async Task Cannot_replace_for_missing_type_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -370,15 +370,15 @@ public async Task Cannot_replace_for_unknown_type_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -409,22 +409,22 @@ public async Task Cannot_replace_for_missing_ID_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' or 'lid' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_replace_for_unknown_ID_in_ref() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -467,13 +467,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); error.Title.Should().Be("The requested resource does not exist."); error.Detail.Should().Be($"Resource of type 'recordCompanies' with ID '{companyId}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); error.Meta.Should().NotContainKey("requestBody"); } @@ -484,7 +484,7 @@ public async Task Cannot_replace_for_incompatible_ID_in_ref() // Arrange string guid = Unknown.StringId.Guid; - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -525,15 +525,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Incompatible 'id' value found."); error.Detail.Should().Be($"Failed to convert '{guid}' of type 'String' to type 'Int16'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref/id"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -566,15 +566,15 @@ public async Task Cannot_replace_for_ID_and_local_ID_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' and 'lid' element are mutually exclusive."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -606,22 +606,22 @@ public async Task Cannot_replace_for_unknown_relationship_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown relationship found."); error.Detail.Should().Be($"Relationship '{Unknown.Relationship}' does not exist on resource type 'performers'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref/relationship"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_replace_for_missing_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -654,22 +654,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'data' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_replace_for_null_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -703,22 +703,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an array, instead of 'null'."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_replace_for_object_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -754,15 +754,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an array, instead of an object."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -801,15 +801,15 @@ public async Task Cannot_replace_for_missing_type_in_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -849,15 +849,15 @@ public async Task Cannot_replace_for_unknown_type_in_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data[0]/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -896,15 +896,15 @@ public async Task Cannot_replace_for_missing_ID_in_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' or 'lid' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -945,22 +945,22 @@ public async Task Cannot_replace_for_ID_and_local_ID_in_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' and 'lid' element are mutually exclusive."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_replace_for_unknown_IDs_in_data() { // Arrange - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); string[] trackIds = [ @@ -1012,20 +1012,20 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(2); + responseDocument.Errors.Should().HaveCount(2); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.NotFound); error1.Title.Should().Be("A related resource does not exist."); error1.Detail.Should().Be($"Related resource of type 'musicTracks' with ID '{trackIds[0]}' in relationship 'tracks' does not exist."); - error1.Source.ShouldNotBeNull(); + error1.Source.Should().NotBeNull(); error1.Source.Pointer.Should().Be("/atomic:operations[0]"); ErrorObject error2 = responseDocument.Errors[1]; error2.StatusCode.Should().Be(HttpStatusCode.NotFound); error2.Title.Should().Be("A related resource does not exist."); error2.Detail.Should().Be($"Related resource of type 'musicTracks' with ID '{trackIds[1]}' in relationship 'tracks' does not exist."); - error2.Source.ShouldNotBeNull(); + error2.Source.Should().NotBeNull(); error2.Source.Pointer.Should().Be("/atomic:operations[0]"); } @@ -1033,7 +1033,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_incompatible_ID_in_data() { // Arrange - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1074,22 +1074,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Incompatible 'id' value found."); error.Detail.Should().Be("Failed to convert 'invalid-guid' of type 'String' to type 'Guid'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data[0]/id"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_replace_for_relationship_mismatch_between_ref_and_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1130,22 +1130,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Incompatible resource type found."); error.Detail.Should().Be("Type 'playlists' is not convertible to type 'performers' of relationship 'performers'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data[0]/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_assign_relationship_with_blocked_capability() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1183,14 +1183,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Relationship cannot be assigned."); error.Detail.Should().Be("The relationship 'occursIn' on resource type 'musicTracks' cannot be assigned to."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref/relationship"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicUpdateToOneRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicUpdateToOneRelationshipTests.cs index 026b4b0e1e..a079f9d829 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicUpdateToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicUpdateToOneRelationshipTests.cs @@ -23,8 +23,8 @@ public AtomicUpdateToOneRelationshipTests(IntegrationTestContext { @@ -68,7 +68,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => lyricInDatabase.Track.Should().BeNull(); List tracksInDatabase = await dbContext.MusicTracks.ToListAsync(); - tracksInDatabase.ShouldHaveCount(1); + tracksInDatabase.Should().HaveCount(1); }); } @@ -76,8 +76,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_OneToOne_relationship_from_dependent_side() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Lyric = _fakers.Lyric.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Lyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -121,7 +121,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => trackInDatabase.Lyric.Should().BeNull(); List lyricsInDatabase = await dbContext.Lyrics.ToListAsync(); - lyricsInDatabase.ShouldHaveCount(1); + lyricsInDatabase.Should().HaveCount(1); }); } @@ -129,8 +129,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_ManyToOne_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.OwnedBy = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.OwnedBy = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -174,7 +174,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => trackInDatabase.OwnedBy.Should().BeNull(); List companiesInDatabase = await dbContext.RecordCompanies.ToListAsync(); - companiesInDatabase.ShouldHaveCount(1); + companiesInDatabase.Should().HaveCount(1); }); } @@ -182,8 +182,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToOne_relationship_from_principal_side() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -227,7 +227,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Lyric lyricInDatabase = await dbContext.Lyrics.Include(lyric => lyric.Track).FirstWithIdAsync(existingLyric.Id); - lyricInDatabase.Track.ShouldNotBeNull(); + lyricInDatabase.Track.Should().NotBeNull(); lyricInDatabase.Track.Id.Should().Be(existingTrack.Id); }); } @@ -236,8 +236,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToOne_relationship_from_dependent_side() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - Lyric existingLyric = _fakers.Lyric.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -281,7 +281,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { MusicTrack trackInDatabase = await dbContext.MusicTracks.Include(musicTrack => musicTrack.Lyric).FirstWithIdAsync(existingTrack.Id); - trackInDatabase.Lyric.ShouldNotBeNull(); + trackInDatabase.Lyric.Should().NotBeNull(); trackInDatabase.Lyric.Id.Should().Be(existingLyric.Id); }); } @@ -290,8 +290,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_ManyToOne_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -335,7 +335,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { MusicTrack trackInDatabase = await dbContext.MusicTracks.Include(musicTrack => musicTrack.OwnedBy).FirstWithIdAsync(existingTrack.Id); - trackInDatabase.OwnedBy.ShouldNotBeNull(); + trackInDatabase.OwnedBy.Should().NotBeNull(); trackInDatabase.OwnedBy.Id.Should().Be(existingCompany.Id); }); } @@ -344,10 +344,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToOne_relationship_from_principal_side() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); - existingLyric.Track = _fakers.MusicTrack.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); + existingLyric.Track = _fakers.MusicTrack.GenerateOne(); - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -392,11 +392,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Lyric lyricInDatabase = await dbContext.Lyrics.Include(lyric => lyric.Track).FirstWithIdAsync(existingLyric.Id); - lyricInDatabase.Track.ShouldNotBeNull(); + lyricInDatabase.Track.Should().NotBeNull(); lyricInDatabase.Track.Id.Should().Be(existingTrack.Id); List tracksInDatabase = await dbContext.MusicTracks.ToListAsync(); - tracksInDatabase.ShouldHaveCount(2); + tracksInDatabase.Should().HaveCount(2); }); } @@ -404,10 +404,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToOne_relationship_from_dependent_side() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Lyric = _fakers.Lyric.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Lyric = _fakers.Lyric.GenerateOne(); - Lyric existingLyric = _fakers.Lyric.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -452,11 +452,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { MusicTrack trackInDatabase = await dbContext.MusicTracks.Include(musicTrack => musicTrack.Lyric).FirstWithIdAsync(existingTrack.Id); - trackInDatabase.Lyric.ShouldNotBeNull(); + trackInDatabase.Lyric.Should().NotBeNull(); trackInDatabase.Lyric.Id.Should().Be(existingLyric.Id); List lyricsInDatabase = await dbContext.Lyrics.ToListAsync(); - lyricsInDatabase.ShouldHaveCount(2); + lyricsInDatabase.Should().HaveCount(2); }); } @@ -464,10 +464,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ManyToOne_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.OwnedBy = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.OwnedBy = _fakers.RecordCompany.GenerateOne(); - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -512,11 +512,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { MusicTrack trackInDatabase = await dbContext.MusicTracks.Include(musicTrack => musicTrack.OwnedBy).FirstWithIdAsync(existingTrack.Id); - trackInDatabase.OwnedBy.ShouldNotBeNull(); + trackInDatabase.OwnedBy.Should().NotBeNull(); trackInDatabase.OwnedBy.Id.Should().Be(existingCompany.Id); List companiesInDatabase = await dbContext.RecordCompanies.ToListAsync(); - companiesInDatabase.ShouldHaveCount(2); + companiesInDatabase.Should().HaveCount(2); }); } @@ -544,15 +544,15 @@ public async Task Cannot_create_for_href_element() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'href' element is not supported."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/href"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -583,15 +583,15 @@ public async Task Cannot_create_for_missing_type_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -623,15 +623,15 @@ public async Task Cannot_create_for_unknown_type_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -662,15 +662,15 @@ public async Task Cannot_create_for_missing_ID_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' or 'lid' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -679,7 +679,7 @@ public async Task Cannot_create_for_unknown_ID_in_ref() // Arrange string trackId = Unknown.StringId.For(); - Lyric existingLyric = _fakers.Lyric.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -717,13 +717,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); error.Title.Should().Be("The requested resource does not exist."); error.Detail.Should().Be($"Resource of type 'musicTracks' with ID '{trackId}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); error.Meta.Should().NotContainKey("requestBody"); } @@ -732,7 +732,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_for_incompatible_ID_in_ref() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -770,15 +770,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Incompatible 'id' value found."); error.Detail.Should().Be("Failed to convert 'invalid-guid' of type 'String' to type 'Guid'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref/id"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -811,15 +811,15 @@ public async Task Cannot_create_for_ID_and_local_ID_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' and 'lid' element are mutually exclusive."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -851,22 +851,22 @@ public async Task Cannot_create_for_unknown_relationship_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown relationship found."); error.Detail.Should().Be($"Relationship '{Unknown.Relationship}' does not exist on resource type 'performers'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref/relationship"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_for_missing_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -899,22 +899,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'data' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_for_array_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -955,15 +955,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object or 'null', instead of an array."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -999,15 +999,15 @@ public async Task Cannot_create_for_missing_type_in_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -1044,15 +1044,15 @@ public async Task Cannot_create_for_unknown_type_in_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -1088,15 +1088,15 @@ public async Task Cannot_create_for_missing_ID_in_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' or 'lid' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -1134,22 +1134,22 @@ public async Task Cannot_create_for_ID_and_local_ID_in_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' and 'lid' element are mutually exclusive."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_for_unknown_ID_in_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1189,13 +1189,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); error.Title.Should().Be("A related resource does not exist."); error.Detail.Should().Be($"Related resource of type 'lyrics' with ID '{lyricId}' in relationship 'lyric' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); error.Meta.Should().NotContainKey("requestBody"); } @@ -1204,7 +1204,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_for_incompatible_ID_in_data() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1242,22 +1242,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Incompatible 'id' value found."); error.Detail.Should().Be("Failed to convert 'invalid-guid' of type 'String' to type 'Guid'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/id"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_for_relationship_mismatch_between_ref_and_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1295,22 +1295,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Incompatible resource type found."); error.Detail.Should().Be("Type 'playlists' is not convertible to type 'lyrics' of relationship 'lyric'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_assign_relationship_with_blocked_capability() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1348,14 +1348,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Relationship cannot be assigned."); error.Detail.Should().Be("The relationship 'language' on resource type 'lyrics' cannot be assigned to."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref/relationship"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicReplaceToManyRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicReplaceToManyRelationshipTests.cs index 10da541794..32db3a5221 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicReplaceToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicReplaceToManyRelationshipTests.cs @@ -23,8 +23,8 @@ public AtomicReplaceToManyRelationshipTests(IntegrationTestContext { @@ -73,7 +73,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => trackInDatabase.Performers.Should().BeEmpty(); List performersInDatabase = await dbContext.Performers.ToListAsync(); - performersInDatabase.ShouldHaveCount(2); + performersInDatabase.Should().HaveCount(2); }); } @@ -81,8 +81,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_ManyToMany_relationship() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); - existingPlaylist.Tracks = _fakers.MusicTrack.Generate(2); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); + existingPlaylist.Tracks = _fakers.MusicTrack.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -132,7 +132,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => List tracksInDatabase = await dbContext.MusicTracks.ToListAsync(); - tracksInDatabase.ShouldHaveCount(2); + tracksInDatabase.Should().HaveCount(2); }); } @@ -140,10 +140,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToMany_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Performers = _fakers.Performer.Generate(1); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Performers = _fakers.Performer.GenerateList(1); - List existingPerformers = _fakers.Performer.Generate(2); + List existingPerformers = _fakers.Performer.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -202,12 +202,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { MusicTrack trackInDatabase = await dbContext.MusicTracks.Include(musicTrack => musicTrack.Performers).FirstWithIdAsync(existingTrack.Id); - trackInDatabase.Performers.ShouldHaveCount(2); + trackInDatabase.Performers.Should().HaveCount(2); trackInDatabase.Performers.Should().ContainSingle(performer => performer.Id == existingPerformers[0].Id); trackInDatabase.Performers.Should().ContainSingle(performer => performer.Id == existingPerformers[1].Id); List performersInDatabase = await dbContext.Performers.ToListAsync(); - performersInDatabase.ShouldHaveCount(3); + performersInDatabase.Should().HaveCount(3); }); } @@ -215,10 +215,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ManyToMany_relationship() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); - existingPlaylist.Tracks = _fakers.MusicTrack.Generate(1); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); + existingPlaylist.Tracks = _fakers.MusicTrack.GenerateList(1); - List existingTracks = _fakers.MusicTrack.Generate(2); + List existingTracks = _fakers.MusicTrack.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -277,13 +277,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Playlist playlistInDatabase = await dbContext.Playlists.Include(playlist => playlist.Tracks).FirstWithIdAsync(existingPlaylist.Id); - playlistInDatabase.Tracks.ShouldHaveCount(2); + playlistInDatabase.Tracks.Should().HaveCount(2); playlistInDatabase.Tracks.Should().ContainSingle(musicTrack => musicTrack.Id == existingTracks[0].Id); playlistInDatabase.Tracks.Should().ContainSingle(musicTrack => musicTrack.Id == existingTracks[1].Id); List tracksInDatabase = await dbContext.MusicTracks.ToListAsync(); - tracksInDatabase.ShouldHaveCount(3); + tracksInDatabase.Should().HaveCount(3); }); } @@ -291,7 +291,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_missing_data_in_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -329,22 +329,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'data' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/performers"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_replace_for_null_data_in_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -383,22 +383,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an array, instead of 'null'."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/performers/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_replace_for_object_data_in_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -439,15 +439,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an array, instead of an object."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/performers/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -491,15 +491,15 @@ public async Task Cannot_replace_for_missing_type_in_relationship_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/tracks/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -544,15 +544,15 @@ public async Task Cannot_replace_for_unknown_type_in_relationship_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/performers/data[0]/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -596,15 +596,15 @@ public async Task Cannot_replace_for_missing_ID_in_relationship_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' or 'lid' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/performers/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -650,22 +650,22 @@ public async Task Cannot_replace_for_ID_and_local_ID_relationship_in_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' and 'lid' element are mutually exclusive."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/performers/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_replace_for_unknown_IDs_in_relationship_data() { // Arrange - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); string[] trackIds = [ @@ -722,20 +722,20 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(2); + responseDocument.Errors.Should().HaveCount(2); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.NotFound); error1.Title.Should().Be("A related resource does not exist."); error1.Detail.Should().Be($"Related resource of type 'musicTracks' with ID '{trackIds[0]}' in relationship 'tracks' does not exist."); - error1.Source.ShouldNotBeNull(); + error1.Source.Should().NotBeNull(); error1.Source.Pointer.Should().Be("/atomic:operations[0]"); ErrorObject error2 = responseDocument.Errors[1]; error2.StatusCode.Should().Be(HttpStatusCode.NotFound); error2.Title.Should().Be("A related resource does not exist."); error2.Detail.Should().Be($"Related resource of type 'musicTracks' with ID '{trackIds[1]}' in relationship 'tracks' does not exist."); - error2.Source.ShouldNotBeNull(); + error2.Source.Should().NotBeNull(); error2.Source.Pointer.Should().Be("/atomic:operations[0]"); } @@ -743,7 +743,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_for_relationship_mismatch() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -789,22 +789,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Incompatible resource type found."); error.Detail.Should().Be("Type 'playlists' is not convertible to type 'performers' of relationship 'performers'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/performers/data[0]/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_assign_relationship_with_blocked_capability() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -850,14 +850,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Relationship cannot be assigned."); error.Detail.Should().Be("The relationship 'occursIn' on resource type 'musicTracks' cannot be assigned to."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/occursIn"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateResourceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateResourceTests.cs index 943d2d9bb4..8bf1ae451b 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateResourceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateResourceTests.cs @@ -29,7 +29,6 @@ public AtomicUpdateResourceTests(IntegrationTestContext(); services.AddSingleton(); - services.AddSingleton(); }); var options = (JsonApiOptions)testContext.Factory.Services.GetRequiredService(); @@ -42,8 +41,8 @@ public async Task Can_update_resources() // Arrange const int elementCount = 5; - List existingTracks = _fakers.MusicTrack.Generate(elementCount); - string[] newTrackTitles = _fakers.MusicTrack.Generate(elementCount).Select(musicTrack => musicTrack.Title).ToArray(); + List existingTracks = _fakers.MusicTrack.GenerateList(elementCount); + string[] newTrackTitles = _fakers.MusicTrack.GenerateList(elementCount).Select(musicTrack => musicTrack.Title).ToArray(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -90,7 +89,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { List tracksInDatabase = await dbContext.MusicTracks.ToListAsync(); - tracksInDatabase.ShouldHaveCount(elementCount); + tracksInDatabase.Should().HaveCount(elementCount); for (int index = 0; index < elementCount; index++) { @@ -106,8 +105,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_without_attributes_or_relationships() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.OwnedBy = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.OwnedBy = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -154,7 +153,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => trackInDatabase.Title.Should().Be(existingTrack.Title); trackInDatabase.Genre.Should().Be(existingTrack.Genre); - trackInDatabase.OwnedBy.ShouldNotBeNull(); + trackInDatabase.OwnedBy.Should().NotBeNull(); trackInDatabase.OwnedBy.Id.Should().Be(existingTrack.OwnedBy.Id); }); } @@ -163,8 +162,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_unknown_attribute() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - string newTitle = _fakers.MusicTrack.Generate().Title; + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + string newTitle = _fakers.MusicTrack.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -201,15 +200,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown attribute found."); error.Detail.Should().Be("Attribute 'doesNotExist' does not exist on resource type 'musicTracks'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/attributes/doesNotExist"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -219,8 +218,8 @@ public async Task Can_update_resource_with_unknown_attribute() var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.AllowUnknownFieldsInRequestBody = true; - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - string newTitle = _fakers.MusicTrack.Generate().Title; + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + string newTitle = _fakers.MusicTrack.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -271,7 +270,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_unknown_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -314,15 +313,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown relationship found."); error.Detail.Should().Be("Relationship 'doesNotExist' does not exist on resource type 'musicTracks'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/doesNotExist"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -332,7 +331,7 @@ public async Task Can_update_resource_with_unknown_relationship() var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.AllowUnknownFieldsInRequestBody = true; - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -382,10 +381,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_partially_update_resource_without_side_effects() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.OwnedBy = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.OwnedBy = _fakers.RecordCompany.GenerateOne(); - string newGenre = _fakers.MusicTrack.Generate().Genre!; + string newGenre = _fakers.MusicTrack.GenerateOne().Genre!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -432,7 +431,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => trackInDatabase.Genre.Should().Be(newGenre); trackInDatabase.ReleasedAt.Should().Be(existingTrack.ReleasedAt); - trackInDatabase.OwnedBy.ShouldNotBeNull(); + trackInDatabase.OwnedBy.Should().NotBeNull(); trackInDatabase.OwnedBy.Id.Should().Be(existingTrack.OwnedBy.Id); }); } @@ -441,13 +440,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_completely_update_resource_without_side_effects() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.OwnedBy = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.OwnedBy = _fakers.RecordCompany.GenerateOne(); - string newTitle = _fakers.MusicTrack.Generate().Title; - decimal? newLengthInSeconds = _fakers.MusicTrack.Generate().LengthInSeconds; - string newGenre = _fakers.MusicTrack.Generate().Genre!; - DateTimeOffset newReleasedAt = _fakers.MusicTrack.Generate().ReleasedAt; + string newTitle = _fakers.MusicTrack.GenerateOne().Title; + decimal? newLengthInSeconds = _fakers.MusicTrack.GenerateOne().LengthInSeconds; + string newGenre = _fakers.MusicTrack.GenerateOne().Genre!; + DateTimeOffset newReleasedAt = _fakers.MusicTrack.GenerateOne().ReleasedAt; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -497,7 +496,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => trackInDatabase.Genre.Should().Be(newGenre); trackInDatabase.ReleasedAt.Should().Be(newReleasedAt); - trackInDatabase.OwnedBy.ShouldNotBeNull(); + trackInDatabase.OwnedBy.Should().NotBeNull(); trackInDatabase.OwnedBy.Id.Should().Be(existingTrack.OwnedBy.Id); }); } @@ -506,8 +505,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_side_effects() { // Arrange - TextLanguage existingLanguage = _fakers.TextLanguage.Generate(); - string newIsoCode = _fakers.TextLanguage.Generate().IsoCode!; + TextLanguage existingLanguage = _fakers.TextLanguage.GenerateOne(); + string newIsoCode = _fakers.TextLanguage.GenerateOne().IsoCode!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -543,16 +542,16 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(1); + responseDocument.Results.Should().HaveCount(1); string isoCode = $"{newIsoCode}{ImplicitlyChangingTextLanguageDefinition.Suffix}"; - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { resource.Type.Should().Be("textLanguages"); - resource.Attributes.ShouldContainKey("isoCode").With(value => value.Should().Be(isoCode)); + resource.Attributes.Should().ContainKey("isoCode").WhoseValue.Should().Be(isoCode); resource.Attributes.Should().NotContainKey("isRightToLeft"); - resource.Relationships.ShouldNotBeEmpty(); + resource.Relationships.Should().NotBeEmpty(); }); await _testContext.RunOnDatabaseAsync(async dbContext => @@ -566,8 +565,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Update_resource_with_side_effects_hides_relationship_data_in_response() { // Arrange - TextLanguage existingLanguage = _fakers.TextLanguage.Generate(); - existingLanguage.Lyrics = _fakers.Lyric.Generate(1); + TextLanguage existingLanguage = _fakers.TextLanguage.GenerateOne(); + existingLanguage.Lyrics = _fakers.Lyric.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -599,11 +598,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Results.ShouldHaveCount(1); + responseDocument.Results.Should().HaveCount(1); - responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => { - resource.Relationships.ShouldNotBeEmpty(); + resource.Relationships.Should().NotBeEmpty(); resource.Relationships.Values.Should().OnlyContain(value => value != null && value.Data.Value == null); }); } @@ -632,23 +631,23 @@ public async Task Cannot_update_resource_for_href_element() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'href' element is not supported."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/href"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_update_resource_for_ref_element() { // Arrange - Performer existingPerformer = _fakers.Performer.Generate(); - string newArtistName = _fakers.Performer.Generate().ArtistName!; + Performer existingPerformer = _fakers.Performer.GenerateOne(); + string newArtistName = _fakers.Performer.GenerateOne().ArtistName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -738,15 +737,15 @@ public async Task Cannot_update_resource_for_missing_type_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -787,15 +786,15 @@ public async Task Cannot_update_resource_for_missing_ID_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' or 'lid' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -838,15 +837,15 @@ public async Task Cannot_update_resource_for_ID_and_local_ID_in_ref() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' and 'lid' element are mutually exclusive."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -872,15 +871,15 @@ public async Task Cannot_update_resource_for_missing_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'data' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -907,22 +906,22 @@ public async Task Cannot_update_resource_for_null_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object, instead of 'null'."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_update_resource_for_array_data() { // Arrange - Performer existingPerformer = _fakers.Performer.Generate(); + Performer existingPerformer = _fakers.Performer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -961,15 +960,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object, instead of an array."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -1005,15 +1004,15 @@ public async Task Cannot_update_resource_for_missing_type_in_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -1049,15 +1048,15 @@ public async Task Cannot_update_resource_for_missing_ID_in_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' or 'lid' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -1095,15 +1094,15 @@ public async Task Cannot_update_resource_for_ID_and_local_ID_in_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' and 'lid' element are mutually exclusive."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -1145,15 +1144,15 @@ public async Task Cannot_update_on_resource_type_mismatch_between_ref_and_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Incompatible resource type found."); error.Detail.Should().Be("Type 'playlists' is not convertible to type 'performers'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -1198,15 +1197,15 @@ public async Task Cannot_update_on_resource_ID_mismatch_between_ref_and_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Conflicting 'id' values found."); error.Detail.Should().Be($"Expected '{performerId1}' instead of '{performerId2}'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/id"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -1248,15 +1247,15 @@ public async Task Cannot_update_on_resource_local_ID_mismatch_between_ref_and_da // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Conflicting 'lid' values found."); error.Detail.Should().Be("Expected 'local-1' instead of 'local-2'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/lid"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -1300,15 +1299,15 @@ public async Task Cannot_update_on_mixture_of_ID_and_local_ID_between_ref_and_da // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -1352,15 +1351,15 @@ public async Task Cannot_update_on_mixture_of_local_ID_and_ID_between_ref_and_da // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'lid' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -1397,15 +1396,15 @@ public async Task Cannot_update_resource_for_unknown_type() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -1444,13 +1443,13 @@ public async Task Cannot_update_resource_for_unknown_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); error.Title.Should().Be("The requested resource does not exist."); error.Detail.Should().Be($"Resource of type 'performers' with ID '{performerId}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); error.Meta.Should().NotContainKey("requestBody"); } @@ -1493,22 +1492,22 @@ public async Task Cannot_update_resource_for_incompatible_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Incompatible 'id' value found."); error.Detail.Should().Be($"Failed to convert '{guid}' of type 'String' to type 'Int32'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/ref/id"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_update_resource_with_readonly_attribute() { // Arrange - Playlist existingPlaylist = _fakers.Playlist.Generate(); + Playlist existingPlaylist = _fakers.Playlist.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1544,22 +1543,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Attribute is read-only."); error.Detail.Should().Be("Attribute 'isArchived' on resource type 'playlists' is read-only."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/attributes/isArchived"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_change_ID_of_existing_resource() { // Arrange - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1595,22 +1594,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Resource ID is read-only."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/attributes/id"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_update_resource_with_incompatible_attribute_value() { // Arrange - Performer existingPerformer = _fakers.Performer.Generate(); + Performer existingPerformer = _fakers.Performer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1646,31 +1645,31 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Incompatible attribute value found."); error.Detail.Should().Be("Failed to convert attribute 'bornAt' with value '123.45' of type 'Number' to type 'DateTimeOffset'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/attributes/bornAt"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_update_resource_with_attributes_and_multiple_relationship_types() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Lyric = _fakers.Lyric.Generate(); - existingTrack.OwnedBy = _fakers.RecordCompany.Generate(); - existingTrack.Performers = _fakers.Performer.Generate(1); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Lyric = _fakers.Lyric.GenerateOne(); + existingTrack.OwnedBy = _fakers.RecordCompany.GenerateOne(); + existingTrack.Performers = _fakers.Performer.GenerateList(1); - string newGenre = _fakers.MusicTrack.Generate().Genre!; + string newGenre = _fakers.MusicTrack.GenerateOne().Genre!; - Lyric existingLyric = _fakers.Lyric.Generate(); - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); - Performer existingPerformer = _fakers.Performer.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); + Performer existingPerformer = _fakers.Performer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1755,13 +1754,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => trackInDatabase.Title.Should().Be(existingTrack.Title); trackInDatabase.Genre.Should().Be(newGenre); - trackInDatabase.Lyric.ShouldNotBeNull(); + trackInDatabase.Lyric.Should().NotBeNull(); trackInDatabase.Lyric.Id.Should().Be(existingLyric.Id); - trackInDatabase.OwnedBy.ShouldNotBeNull(); + trackInDatabase.OwnedBy.Should().NotBeNull(); trackInDatabase.OwnedBy.Id.Should().Be(existingCompany.Id); - trackInDatabase.Performers.ShouldHaveCount(1); + trackInDatabase.Performers.Should().HaveCount(1); trackInDatabase.Performers[0].Id.Should().Be(existingPerformer.Id); }); } @@ -1770,7 +1769,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_assign_attribute_with_blocked_capability() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1806,14 +1805,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Attribute value cannot be assigned when updating resource."); error.Detail.Should().Be("The attribute 'createdAt' on resource type 'lyrics' cannot be assigned to."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/attributes/createdAt"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateToOneRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateToOneRelationshipTests.cs index 931e75e789..a8c6881616 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateToOneRelationshipTests.cs @@ -23,8 +23,8 @@ public AtomicUpdateToOneRelationshipTests(IntegrationTestContext { @@ -73,7 +73,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => lyricInDatabase.Track.Should().BeNull(); List tracksInDatabase = await dbContext.MusicTracks.ToListAsync(); - tracksInDatabase.ShouldHaveCount(1); + tracksInDatabase.Should().HaveCount(1); }); } @@ -81,8 +81,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_OneToOne_relationship_from_dependent_side() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Lyric = _fakers.Lyric.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Lyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -131,7 +131,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => trackInDatabase.Lyric.Should().BeNull(); List lyricsInDatabase = await dbContext.Lyrics.ToListAsync(); - lyricsInDatabase.ShouldHaveCount(1); + lyricsInDatabase.Should().HaveCount(1); }); } @@ -139,8 +139,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_ManyToOne_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.OwnedBy = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.OwnedBy = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -189,7 +189,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => trackInDatabase.OwnedBy.Should().BeNull(); List companiesInDatabase = await dbContext.RecordCompanies.ToListAsync(); - companiesInDatabase.ShouldHaveCount(1); + companiesInDatabase.Should().HaveCount(1); }); } @@ -197,8 +197,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToOne_relationship_from_principal_side() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -247,7 +247,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Lyric lyricInDatabase = await dbContext.Lyrics.Include(lyric => lyric.Track).FirstWithIdAsync(existingLyric.Id); - lyricInDatabase.Track.ShouldNotBeNull(); + lyricInDatabase.Track.Should().NotBeNull(); lyricInDatabase.Track.Id.Should().Be(existingTrack.Id); }); } @@ -256,8 +256,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToOne_relationship_from_dependent_side() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - Lyric existingLyric = _fakers.Lyric.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -306,7 +306,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { MusicTrack trackInDatabase = await dbContext.MusicTracks.Include(musicTrack => musicTrack.Lyric).FirstWithIdAsync(existingTrack.Id); - trackInDatabase.Lyric.ShouldNotBeNull(); + trackInDatabase.Lyric.Should().NotBeNull(); trackInDatabase.Lyric.Id.Should().Be(existingLyric.Id); }); } @@ -315,8 +315,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_ManyToOne_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -365,7 +365,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { MusicTrack trackInDatabase = await dbContext.MusicTracks.Include(musicTrack => musicTrack.OwnedBy).FirstWithIdAsync(existingTrack.Id); - trackInDatabase.OwnedBy.ShouldNotBeNull(); + trackInDatabase.OwnedBy.Should().NotBeNull(); trackInDatabase.OwnedBy.Id.Should().Be(existingCompany.Id); }); } @@ -374,10 +374,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToOne_relationship_from_principal_side() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); - existingLyric.Track = _fakers.MusicTrack.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); + existingLyric.Track = _fakers.MusicTrack.GenerateOne(); - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -427,11 +427,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Lyric lyricInDatabase = await dbContext.Lyrics.Include(lyric => lyric.Track).FirstWithIdAsync(existingLyric.Id); - lyricInDatabase.Track.ShouldNotBeNull(); + lyricInDatabase.Track.Should().NotBeNull(); lyricInDatabase.Track.Id.Should().Be(existingTrack.Id); List tracksInDatabase = await dbContext.MusicTracks.ToListAsync(); - tracksInDatabase.ShouldHaveCount(2); + tracksInDatabase.Should().HaveCount(2); }); } @@ -439,10 +439,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToOne_relationship_from_dependent_side() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.Lyric = _fakers.Lyric.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.Lyric = _fakers.Lyric.GenerateOne(); - Lyric existingLyric = _fakers.Lyric.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -492,11 +492,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { MusicTrack trackInDatabase = await dbContext.MusicTracks.Include(musicTrack => musicTrack.Lyric).FirstWithIdAsync(existingTrack.Id); - trackInDatabase.Lyric.ShouldNotBeNull(); + trackInDatabase.Lyric.Should().NotBeNull(); trackInDatabase.Lyric.Id.Should().Be(existingLyric.Id); List lyricsInDatabase = await dbContext.Lyrics.ToListAsync(); - lyricsInDatabase.ShouldHaveCount(2); + lyricsInDatabase.Should().HaveCount(2); }); } @@ -504,10 +504,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ManyToOne_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - existingTrack.OwnedBy = _fakers.RecordCompany.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); + existingTrack.OwnedBy = _fakers.RecordCompany.GenerateOne(); - RecordCompany existingCompany = _fakers.RecordCompany.Generate(); + RecordCompany existingCompany = _fakers.RecordCompany.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -557,11 +557,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { MusicTrack trackInDatabase = await dbContext.MusicTracks.Include(musicTrack => musicTrack.OwnedBy).FirstWithIdAsync(existingTrack.Id); - trackInDatabase.OwnedBy.ShouldNotBeNull(); + trackInDatabase.OwnedBy.Should().NotBeNull(); trackInDatabase.OwnedBy.Id.Should().Be(existingCompany.Id); List companiesInDatabase = await dbContext.RecordCompanies.ToListAsync(); - companiesInDatabase.ShouldHaveCount(2); + companiesInDatabase.Should().HaveCount(2); }); } @@ -569,7 +569,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_for_null_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -605,22 +605,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object, instead of 'null'."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/lyric"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_for_missing_data_in_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -658,22 +658,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'data' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/lyric"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_for_array_data_in_relationship() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -719,15 +719,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object or 'null', instead of an array."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/lyric/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -768,15 +768,15 @@ public async Task Cannot_create_for_missing_type_in_relationship_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/track/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -818,15 +818,15 @@ public async Task Cannot_create_for_unknown_type_in_relationship_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/lyric/data/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -867,15 +867,15 @@ public async Task Cannot_create_for_missing_ID_in_relationship_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' or 'lid' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/lyric/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -918,22 +918,22 @@ public async Task Cannot_create_for_ID_and_local_ID_in_relationship_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' and 'lid' element are mutually exclusive."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/lyric/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_for_unknown_ID_in_relationship_data() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -978,13 +978,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); error.Title.Should().Be("A related resource does not exist."); error.Detail.Should().Be($"Related resource of type 'lyrics' with ID '{lyricId}' in relationship 'lyric' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]"); error.Meta.Should().NotContainKey("requestBody"); } @@ -993,7 +993,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_for_relationship_mismatch() { // Arrange - MusicTrack existingTrack = _fakers.MusicTrack.Generate(); + MusicTrack existingTrack = _fakers.MusicTrack.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1036,22 +1036,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Incompatible resource type found."); error.Detail.Should().Be("Type 'playlists' is not convertible to type 'lyrics' of relationship 'lyric'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/lyric/data/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_assign_relationship_with_blocked_capability() { // Arrange - Lyric existingLyric = _fakers.Lyric.Generate(); + Lyric existingLyric = _fakers.Lyric.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1094,14 +1094,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Relationship cannot be assigned."); error.Detail.Should().Be("The relationship 'language' on resource type 'lyrics' cannot be assigned to."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/language"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/OperationsController.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/OperationsController.cs index de1cd02c20..d7f252c3bd 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/OperationsController.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/OperationsController.cs @@ -12,8 +12,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.Authorization.Scopes; public sealed class OperationsController( IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, IOperationsProcessor processor, IJsonApiRequest request, - ITargetedFields targetedFields, IAtomicOperationFilter operationFilter) : JsonApiOperationsController(options, resourceGraph, loggerFactory, processor, - request, targetedFields, operationFilter) + ITargetedFields targetedFields, IAtomicOperationFilter operationFilter) + : JsonApiOperationsController(options, resourceGraph, loggerFactory, processor, request, targetedFields, operationFilter) { public override async Task PostOperationsAsync(IList operations, CancellationToken cancellationToken) { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopeOperationsTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopeOperationsTests.cs index 57af5bce7a..d8834ce7fa 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopeOperationsTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopeOperationsTests.cs @@ -1,6 +1,7 @@ using System.Net; using System.Net.Http.Headers; using FluentAssertions; +using JsonApiDotNetCore.Middleware; using JsonApiDotNetCore.Serialization.Objects; using TestBuildingBlocks; using Xunit; @@ -27,8 +28,8 @@ public ScopeOperationsTests(IntegrationTestContext setRequestHeaders = headers => headers.Add(ScopeHeaderName, "read:genres"); + Action setRequestHeaders = headers => + { + headers.Add(ScopeHeaderName, "read:genres"); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(JsonApiMediaType.AtomicOperations.ToString())); + }; // Act (HttpResponseMessage httpResponse, Document responseDocument) = - await _testContext.ExecutePostAtomicAsync(route, requestBody, setRequestHeaders: setRequestHeaders); + await _testContext.ExecutePostAsync(route, requestBody, contentType, setRequestHeaders); // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: write:genres."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -145,8 +151,8 @@ public async Task Cannot_create_resource_with_read_scope() public async Task Cannot_update_resources_without_scopes() { // Arrange - string newTitle = _fakers.Movie.Generate().Title; - DateTime newBornAt = _fakers.Actor.Generate().BornAt; + string newTitle = _fakers.Movie.GenerateOne().Title; + DateTime newBornAt = _fakers.Actor.GenerateOne().BornAt; var requestBody = new { @@ -189,13 +195,13 @@ public async Task Cannot_update_resources_without_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: write:actors write:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -203,7 +209,7 @@ public async Task Cannot_update_resources_without_scopes() public async Task Cannot_update_resource_with_relationships_without_scopes() { // Arrange - string newTitle = _fakers.Movie.Generate().Title; + string newTitle = _fakers.Movie.GenerateOne().Title; var requestBody = new { @@ -247,13 +253,13 @@ public async Task Cannot_update_resource_with_relationships_without_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: write:actors write:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -294,13 +300,13 @@ public async Task Cannot_delete_resources_without_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: write:actors write:genres."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -334,13 +340,13 @@ public async Task Cannot_update_ToOne_relationship_without_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: write:genres write:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -374,13 +380,13 @@ public async Task Cannot_update_ToMany_relationship_without_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: write:actors write:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -414,13 +420,13 @@ public async Task Cannot_add_to_ToMany_relationship_without_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: write:actors write:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -454,13 +460,13 @@ public async Task Cannot_remove_from_ToMany_relationship_without_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: write:actors write:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopeReadTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopeReadTests.cs index 98e5ccb7af..91530044df 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopeReadTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopeReadTests.cs @@ -34,13 +34,13 @@ public async Task Cannot_get_primary_resources_without_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: read:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -58,13 +58,13 @@ public async Task Cannot_get_primary_resources_with_incorrect_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: read:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -72,8 +72,8 @@ public async Task Cannot_get_primary_resources_with_incorrect_scopes() public async Task Can_get_primary_resources_with_correct_scope() { // Arrange - Movie movie = _fakers.Movie.Generate(); - movie.Genre = _fakers.Genre.Generate(); + Movie movie = _fakers.Movie.GenerateOne(); + movie.Genre = _fakers.Genre.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -92,18 +92,18 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("movies"); responseDocument.Data.ManyValue[0].Id.Should().Be(movie.StringId); - responseDocument.Data.ManyValue[0].Attributes.ShouldNotBeEmpty(); - responseDocument.Data.ManyValue[0].Relationships.ShouldNotBeEmpty(); + responseDocument.Data.ManyValue[0].Attributes.Should().NotBeEmpty(); + responseDocument.Data.ManyValue[0].Relationships.Should().NotBeEmpty(); } [Fact] public async Task Can_get_primary_resources_with_write_scope() { // Arrange - Genre genre = _fakers.Genre.Generate(); + Genre genre = _fakers.Genre.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -122,18 +122,18 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("genres"); responseDocument.Data.ManyValue[0].Id.Should().Be(genre.StringId); - responseDocument.Data.ManyValue[0].Attributes.ShouldNotBeEmpty(); - responseDocument.Data.ManyValue[0].Relationships.ShouldNotBeEmpty(); + responseDocument.Data.ManyValue[0].Attributes.Should().NotBeEmpty(); + responseDocument.Data.ManyValue[0].Relationships.Should().NotBeEmpty(); } [Fact] public async Task Can_get_primary_resources_with_redundant_scopes() { // Arrange - Actor actor = _fakers.Actor.Generate(); + Actor actor = _fakers.Actor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -152,11 +152,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("actors"); responseDocument.Data.ManyValue[0].Id.Should().Be(actor.StringId); - responseDocument.Data.ManyValue[0].Attributes.ShouldNotBeEmpty(); - responseDocument.Data.ManyValue[0].Relationships.ShouldNotBeEmpty(); + responseDocument.Data.ManyValue[0].Attributes.Should().NotBeEmpty(); + responseDocument.Data.ManyValue[0].Relationships.Should().NotBeEmpty(); } [Fact] @@ -171,13 +171,13 @@ public async Task Cannot_get_primary_resource_without_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: read:actors."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -193,13 +193,13 @@ public async Task Cannot_get_secondary_resource_without_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: read:genres read:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -215,13 +215,13 @@ public async Task Cannot_get_secondary_resources_without_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: read:genres read:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -237,13 +237,13 @@ public async Task Cannot_get_ToOne_relationship_without_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: read:genres read:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -259,13 +259,13 @@ public async Task Cannot_get_ToMany_relationship_without_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: read:genres read:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -283,13 +283,13 @@ public async Task Cannot_include_with_insufficient_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: read:actors read:genres read:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -307,13 +307,13 @@ public async Task Cannot_filter_with_insufficient_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: read:actors read:genres read:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -331,13 +331,13 @@ public async Task Cannot_sort_with_insufficient_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: read:actors read:genres read:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopeWriteTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopeWriteTests.cs index bb9d1d05cb..ef1e7d5aca 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopeWriteTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopeWriteTests.cs @@ -24,7 +24,7 @@ public ScopeWriteTests(IntegrationTestContext, Sc public async Task Cannot_create_resource_without_scopes() { // Arrange - Movie newMovie = _fakers.Movie.Generate(); + Movie newMovie = _fakers.Movie.GenerateOne(); var requestBody = new { @@ -48,13 +48,13 @@ public async Task Cannot_create_resource_without_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: write:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -62,7 +62,7 @@ public async Task Cannot_create_resource_without_scopes() public async Task Cannot_create_resource_with_relationships_without_scopes() { // Arrange - Movie newMovie = _fakers.Movie.Generate(); + Movie newMovie = _fakers.Movie.GenerateOne(); var requestBody = new { @@ -108,13 +108,13 @@ public async Task Cannot_create_resource_with_relationships_without_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: write:actors write:genres write:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -122,7 +122,7 @@ public async Task Cannot_create_resource_with_relationships_without_scopes() public async Task Cannot_create_resource_with_relationships_with_read_scopes() { // Arrange - Movie newMovie = _fakers.Movie.Generate(); + Movie newMovie = _fakers.Movie.GenerateOne(); var requestBody = new { @@ -171,13 +171,13 @@ public async Task Cannot_create_resource_with_relationships_with_read_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: write:actors write:genres write:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -185,7 +185,7 @@ public async Task Cannot_create_resource_with_relationships_with_read_scopes() public async Task Cannot_update_resource_without_scopes() { // Arrange - string newTitle = _fakers.Movie.Generate().Title; + string newTitle = _fakers.Movie.GenerateOne().Title; var requestBody = new { @@ -208,13 +208,13 @@ public async Task Cannot_update_resource_without_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: write:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -222,7 +222,7 @@ public async Task Cannot_update_resource_without_scopes() public async Task Cannot_update_resource_with_relationships_without_scopes() { // Arrange - string newTitle = _fakers.Movie.Generate().Title; + string newTitle = _fakers.Movie.GenerateOne().Title; var requestBody = new { @@ -267,13 +267,13 @@ public async Task Cannot_update_resource_with_relationships_without_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: write:actors write:genres write:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -289,13 +289,13 @@ public async Task Cannot_delete_resource_without_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: write:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -320,13 +320,13 @@ public async Task Cannot_update_ToOne_relationship_without_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: write:genres write:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -354,13 +354,13 @@ public async Task Cannot_update_ToMany_relationship_without_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: write:actors write:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -388,13 +388,13 @@ public async Task Cannot_add_to_ToMany_relationship_without_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: write:actors write:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } @@ -422,13 +422,13 @@ public async Task Cannot_remove_from_ToMany_relationship_without_scopes() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Unauthorized); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Unauthorized); error.Title.Should().Be("Insufficient permissions to perform this request."); error.Detail.Should().Be("Performing this request requires the following scopes: write:actors write:movies."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be(ScopeHeaderName); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopesDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopesDbContext.cs index 81af9423d2..296ded9b42 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopesDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Authorization/Scopes/ScopesDbContext.cs @@ -5,7 +5,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.Authorization.Scopes; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class ScopesDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class ScopesDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet Movies => Set(); public DbSet Actors => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Blobs/BlobDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Blobs/BlobDbContext.cs index 64c8cd7569..89601169e5 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Blobs/BlobDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Blobs/BlobDbContext.cs @@ -5,7 +5,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.Blobs; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class BlobDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class BlobDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet ImageContainers => Set(); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Blobs/BlobTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Blobs/BlobTests.cs index fca26c66c3..3716c56214 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Blobs/BlobTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Blobs/BlobTests.cs @@ -26,7 +26,7 @@ public BlobTests(IntegrationTestContext, BlobDbCo public async Task Can_get_primary_resource_by_ID() { // Arrange - ImageContainer container = _fakers.ImageContainer.Generate(); + ImageContainer container = _fakers.ImageContainer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -42,12 +42,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("imageContainers"); responseDocument.Data.SingleValue.Id.Should().Be(container.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("fileName").With(value => value.Should().Be(container.FileName)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("data").As().With(value => value.Should().Equal(container.Data)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("thumbnail").As().With(value => value.Should().Equal(container.Thumbnail)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("fileName").WhoseValue.Should().Be(container.FileName); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("data").WhoseValue.As().Should().Equal(container.Data); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("thumbnail").WhoseValue.As().Should().Equal(container.Thumbnail); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); } @@ -55,7 +55,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_resource() { // Arrange - ImageContainer newContainer = _fakers.ImageContainer.Generate(); + ImageContainer newContainer = _fakers.ImageContainer.GenerateOne(); var requestBody = new { @@ -79,14 +79,14 @@ public async Task Can_create_resource() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("imageContainers"); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("fileName").With(value => value.Should().Be(newContainer.FileName)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("data").As().With(value => value.Should().Equal(newContainer.Data)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("thumbnail").As().With(value => value.Should().Equal(newContainer.Thumbnail)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("fileName").WhoseValue.Should().Be(newContainer.FileName); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("data").WhoseValue.As().Should().Equal(newContainer.Data); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("thumbnail").WhoseValue.As().Should().Equal(newContainer.Thumbnail); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); - long newContainerId = long.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + long newContainerId = long.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -102,10 +102,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource() { // Arrange - ImageContainer existingContainer = _fakers.ImageContainer.Generate(); + ImageContainer existingContainer = _fakers.ImageContainer.GenerateOne(); - byte[] newData = _fakers.ImageContainer.Generate().Data; - byte[] newThumbnail = _fakers.ImageContainer.Generate().Thumbnail!; + byte[] newData = _fakers.ImageContainer.GenerateOne().Data; + byte[] newThumbnail = _fakers.ImageContainer.GenerateOne().Thumbnail!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -135,12 +135,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("imageContainers"); responseDocument.Data.SingleValue.Id.Should().Be(existingContainer.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("fileName").With(value => value.Should().Be(existingContainer.FileName)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("data").As().With(value => value.Should().Equal(newData)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("thumbnail").As().With(value => value.Should().Equal(newThumbnail)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("fileName").WhoseValue.Should().Be(existingContainer.FileName); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("data").WhoseValue.As().With(value => value.Should().Equal(newData)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("thumbnail").WhoseValue.As().With(value => value.Should().Equal(newThumbnail)); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); await _testContext.RunOnDatabaseAsync(async dbContext => @@ -157,7 +157,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_empty_blob() { // Arrange - ImageContainer existingContainer = _fakers.ImageContainer.Generate(); + ImageContainer existingContainer = _fakers.ImageContainer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -186,11 +186,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("imageContainers"); responseDocument.Data.SingleValue.Id.Should().Be(existingContainer.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("fileName").With(value => value.Should().Be(existingContainer.FileName)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("data").As().With(value => value.Should().BeEmpty()); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("fileName").WhoseValue.Should().Be(existingContainer.FileName); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("data").WhoseValue.As().With(value => value.Should().BeEmpty()); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); await _testContext.RunOnDatabaseAsync(async dbContext => @@ -206,7 +206,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_null_blob() { // Arrange - ImageContainer existingContainer = _fakers.ImageContainer.Generate(); + ImageContainer existingContainer = _fakers.ImageContainer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -235,11 +235,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("imageContainers"); responseDocument.Data.SingleValue.Id.Should().Be(existingContainer.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("fileName").With(value => value.Should().Be(existingContainer.FileName)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("thumbnail").With(value => value.Should().BeNull()); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("fileName").WhoseValue.Should().Be(existingContainer.FileName); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("thumbnail").WhoseValue.Should().BeNull(); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); await _testContext.RunOnDatabaseAsync(async dbContext => diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/Car.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/Car.cs index d61d378db7..f77626f13e 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/Car.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/Car.cs @@ -12,13 +12,13 @@ public sealed class Car : Identifiable [NotMapped] public override string? Id { - get => RegionId == default && LicensePlate == default ? null : $"{RegionId}:{LicensePlate}"; + get => RegionId == 0 && LicensePlate == null ? null : $"{RegionId}:{LicensePlate}"; set { if (value == null) { - RegionId = default; - LicensePlate = default; + RegionId = 0; + LicensePlate = null; return; } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarCompositeKeyAwareRepository.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarCompositeKeyAwareRepository.cs index b818c0f094..089f487908 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarCompositeKeyAwareRepository.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarCompositeKeyAwareRepository.cs @@ -39,8 +39,7 @@ private void RecursiveRewriteFilterInLayer(QueryLayer queryLayer) if (queryLayer.Selection is { IsEmpty: false }) { - foreach (QueryLayer? nextLayer in queryLayer.Selection.GetResourceTypes() - .Select(resourceType => queryLayer.Selection.GetOrCreateSelectors(resourceType)) + foreach (QueryLayer? nextLayer in queryLayer.Selection.GetResourceTypes().Select(queryLayer.Selection.GetOrCreateSelectors) .SelectMany(selectors => selectors.Select(selector => selector.Value).Where(layer => layer != null))) { RecursiveRewriteFilterInLayer(nextLayer!); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarExpressionRewriter.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarExpressionRewriter.cs index c85a2b2a31..e7802bcb09 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarExpressionRewriter.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarExpressionRewriter.cs @@ -89,14 +89,14 @@ private QueryExpression RewriteFilterOnCarStringIds(ResourceFieldChainExpression StringId = carStringId }; - FilterExpression keyComparison = CreateEqualityComparisonOnCompositeKey(existingCarIdChain, tempCar.RegionId, tempCar.LicensePlate!); + LogicalExpression keyComparison = CreateEqualityComparisonOnCompositeKey(existingCarIdChain, tempCar.RegionId, tempCar.LicensePlate!); outerTermsBuilder.Add(keyComparison); } return outerTermsBuilder.Count == 1 ? outerTermsBuilder[0] : new LogicalExpression(LogicalOperator.Or, outerTermsBuilder.ToImmutable()); } - private FilterExpression CreateEqualityComparisonOnCompositeKey(ResourceFieldChainExpression existingCarIdChain, long regionIdValue, + private LogicalExpression CreateEqualityComparisonOnCompositeKey(ResourceFieldChainExpression existingCarIdChain, long regionIdValue, string licensePlateValue) { ResourceFieldChainExpression regionIdChain = ReplaceLastAttributeInChain(existingCarIdChain, _regionIdAttribute); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CompositeDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CompositeDbContext.cs index 3d10a70df6..c4f8e0f26a 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CompositeDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CompositeDbContext.cs @@ -7,7 +7,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.CompositeKeys; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class CompositeDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class CompositeDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet Cars => Set(); public DbSet Engines => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CompositeKeyTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CompositeKeyTests.cs index a015ac52fa..3ea92e7c17 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CompositeKeyTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CompositeKeyTests.cs @@ -32,7 +32,7 @@ public CompositeKeyTests(IntegrationTestContext { @@ -49,7 +49,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(car.StringId); } @@ -57,7 +57,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resource_by_ID() { // Arrange - Car car = _fakers.Car.Generate(); + Car car = _fakers.Car.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -74,7 +74,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(car.StringId); } @@ -82,7 +82,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_on_ID() { // Arrange - Car car = _fakers.Car.Generate(); + Car car = _fakers.Car.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -99,7 +99,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(car.StringId); } @@ -107,7 +107,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_select_ID() { // Arrange - Car car = _fakers.Car.Generate(); + Car car = _fakers.Car.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -124,7 +124,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(car.StringId); } @@ -132,9 +132,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_resource() { // Arrange - Engine existingEngine = _fakers.Engine.Generate(); + Engine existingEngine = _fakers.Engine.GenerateOne(); - Car newCar = _fakers.Car.Generate(); + Car newCar = _fakers.Car.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -181,7 +181,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Car? carInDatabase = await dbContext.Cars.FirstOrDefaultAsync(car => car.RegionId == newCar.RegionId && car.LicensePlate == newCar.LicensePlate); - carInDatabase.ShouldNotBeNull(); + carInDatabase.Should().NotBeNull(); carInDatabase.Id.Should().Be($"{newCar.RegionId}:{newCar.LicensePlate}"); }); } @@ -190,8 +190,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToOne_relationship() { // Arrange - Car existingCar = _fakers.Car.Generate(); - Engine existingEngine = _fakers.Engine.Generate(); + Car existingCar = _fakers.Car.GenerateOne(); + Engine existingEngine = _fakers.Engine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -234,7 +234,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Engine engineInDatabase = await dbContext.Engines.Include(engine => engine.Car).FirstWithIdAsync(existingEngine.Id); - engineInDatabase.Car.ShouldNotBeNull(); + engineInDatabase.Car.Should().NotBeNull(); engineInDatabase.Car.Id.Should().Be(existingCar.StringId); }); } @@ -243,8 +243,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_OneToOne_relationship() { // Arrange - Engine existingEngine = _fakers.Engine.Generate(); - existingEngine.Car = _fakers.Car.Generate(); + Engine existingEngine = _fakers.Engine.GenerateOne(); + existingEngine.Car = _fakers.Car.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -291,8 +291,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_OneToMany_relationship() { // Arrange - Dealership existingDealership = _fakers.Dealership.Generate(); - existingDealership.Inventory = _fakers.Car.Generate(2).ToHashSet(); + Dealership existingDealership = _fakers.Dealership.GenerateOne(); + existingDealership.Inventory = _fakers.Car.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -327,7 +327,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Dealership dealershipInDatabase = await dbContext.Dealerships.Include(dealership => dealership.Inventory).FirstWithIdAsync(existingDealership.Id); - dealershipInDatabase.Inventory.ShouldHaveCount(1); + dealershipInDatabase.Inventory.Should().HaveCount(1); dealershipInDatabase.Inventory.Should().ContainSingle(car => car.Id == existingDealership.Inventory.ElementAt(1).Id); }); } @@ -336,8 +336,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_to_OneToMany_relationship() { // Arrange - Dealership existingDealership = _fakers.Dealership.Generate(); - Car existingCar = _fakers.Car.Generate(); + Dealership existingDealership = _fakers.Dealership.GenerateOne(); + Car existingCar = _fakers.Car.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -372,7 +372,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Dealership dealershipInDatabase = await dbContext.Dealerships.Include(dealership => dealership.Inventory).FirstWithIdAsync(existingDealership.Id); - dealershipInDatabase.Inventory.ShouldHaveCount(1); + dealershipInDatabase.Inventory.Should().HaveCount(1); dealershipInDatabase.Inventory.Should().ContainSingle(car => car.Id == existingCar.Id); }); } @@ -381,10 +381,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToMany_relationship() { // Arrange - Dealership existingDealership = _fakers.Dealership.Generate(); - existingDealership.Inventory = _fakers.Car.Generate(2).ToHashSet(); + Dealership existingDealership = _fakers.Dealership.GenerateOne(); + existingDealership.Inventory = _fakers.Car.GenerateSet(2); - Car existingCar = _fakers.Car.Generate(); + Car existingCar = _fakers.Car.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -424,7 +424,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Dealership dealershipInDatabase = await dbContext.Dealerships.Include(dealership => dealership.Inventory).FirstWithIdAsync(existingDealership.Id); - dealershipInDatabase.Inventory.ShouldHaveCount(2); + dealershipInDatabase.Inventory.Should().HaveCount(2); dealershipInDatabase.Inventory.Should().ContainSingle(car => car.Id == existingCar.Id); dealershipInDatabase.Inventory.Should().ContainSingle(car => car.Id == existingDealership.Inventory.ElementAt(0).Id); }); @@ -434,9 +434,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_from_ManyToOne_relationship_for_unknown_relationship_ID() { // Arrange - Dealership existingDealership = _fakers.Dealership.Generate(); + Dealership existingDealership = _fakers.Dealership.GenerateOne(); - string unknownCarId = _fakers.Car.Generate().StringId!; + string unknownCarId = _fakers.Car.GenerateOne().StringId!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -465,7 +465,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -477,7 +477,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource() { // Arrange - Car existingCar = _fakers.Car.Generate(); + Car existingCar = _fakers.Car.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -509,8 +509,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_ManyToMany_relationship() { // Arrange - Dealership existingDealership = _fakers.Dealership.Generate(); - existingDealership.SoldCars = _fakers.Car.Generate(2).ToHashSet(); + Dealership existingDealership = _fakers.Dealership.GenerateOne(); + existingDealership.SoldCars = _fakers.Car.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -545,11 +545,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Dealership dealershipInDatabase = await dbContext.Dealerships.Include(dealership => dealership.SoldCars).FirstWithIdAsync(existingDealership.Id); - dealershipInDatabase.SoldCars.ShouldHaveCount(1); + dealershipInDatabase.SoldCars.Should().HaveCount(1); dealershipInDatabase.SoldCars.Single().Id.Should().Be(existingDealership.SoldCars.ElementAt(0).Id); List carsInDatabase = await dbContext.Cars.ToListAsync(); - carsInDatabase.ShouldHaveCount(2); + carsInDatabase.Should().HaveCount(2); }); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/AcceptHeaderTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/AcceptHeaderTests.cs index 27e89d98f8..d7b1616501 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/AcceptHeaderTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/AcceptHeaderTests.cs @@ -20,52 +20,6 @@ public AcceptHeaderTests(IntegrationTestContext testContext.UseController(); } - [Fact] - public async Task Permits_no_Accept_headers() - { - // Arrange - const string route = "/policies"; - - // Act - (HttpResponseMessage httpResponse, _) = await _testContext.ExecuteGetAsync(route); - - // Assert - httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - } - - [Fact] - public async Task Permits_no_Accept_headers_at_operations_endpoint() - { - // Arrange - var requestBody = new - { - atomic__operations = new[] - { - new - { - op = "add", - data = new - { - type = "policies", - attributes = new - { - name = "some" - } - } - } - } - }; - - const string route = "/operations"; - const string contentType = HeaderConstants.AtomicOperationsMediaType; - - // Act - (HttpResponseMessage httpResponse, _) = await _testContext.ExecutePostAsync(route, requestBody, contentType); - - // Assert - httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - } - [Fact] public async Task Permits_global_wildcard_in_Accept_headers() { @@ -84,8 +38,8 @@ public async Task Permits_global_wildcard_in_Accept_headers() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - httpResponse.Content.Headers.ContentType.ShouldNotBeNull(); - httpResponse.Content.Headers.ContentType.ToString().Should().Be(HeaderConstants.MediaType); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); } [Fact] @@ -106,8 +60,8 @@ public async Task Permits_application_wildcard_in_Accept_headers() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - httpResponse.Content.Headers.ContentType.ShouldNotBeNull(); - httpResponse.Content.Headers.ContentType.ToString().Should().Be(HeaderConstants.MediaType); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); } [Fact] @@ -119,10 +73,10 @@ public async Task Permits_JsonApi_without_parameters_in_Accept_headers() Action setRequestHeaders = headers => { headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("text/html")); - headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{HeaderConstants.MediaType}; profile=some")); - headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{HeaderConstants.MediaType}; ext=other")); - headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{HeaderConstants.MediaType}; unknown=unexpected")); - headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{HeaderConstants.MediaType}; q=0.3")); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{JsonApiMediaType.Default}; profile=some")); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{JsonApiMediaType.Default}; ext=other")); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{JsonApiMediaType.Default}; unknown=unexpected")); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{JsonApiMediaType.Default}; q=0.3")); }; // Act @@ -131,8 +85,8 @@ public async Task Permits_JsonApi_without_parameters_in_Accept_headers() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - httpResponse.Content.Headers.ContentType.ShouldNotBeNull(); - httpResponse.Content.Headers.ContentType.ToString().Should().Be(HeaderConstants.MediaType); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); } [Fact] @@ -159,16 +113,16 @@ public async Task Prefers_JsonApi_with_AtomicOperations_extension_in_Accept_head }; const string route = "/operations"; - const string contentType = HeaderConstants.RelaxedAtomicOperationsMediaType; + string contentType = JsonApiMediaType.AtomicOperations.ToString(); Action setRequestHeaders = headers => { headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("text/html")); - headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{HeaderConstants.MediaType}; profile=some")); - headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(HeaderConstants.MediaType)); - headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{HeaderConstants.MediaType}; unknown=unexpected")); - headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{HeaderConstants.MediaType};EXT=atomic-operations; q=0.2")); - headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{HeaderConstants.MediaType};EXT=\"https://jsonapi.org/ext/atomic\"; q=0.8")); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{JsonApiMediaType.Default}; profile=some")); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(JsonApiMediaType.Default.ToString())); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{JsonApiMediaType.Default}; unknown=unexpected")); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{JsonApiMediaType.Default};EXT=atomic; q=0.8")); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{JsonApiMediaType.Default};EXT=\"https://jsonapi.org/ext/atomic\"; q=0.2")); }; // Act @@ -177,8 +131,8 @@ public async Task Prefers_JsonApi_with_AtomicOperations_extension_in_Accept_head // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - httpResponse.Content.Headers.ContentType.ShouldNotBeNull(); - httpResponse.Content.Headers.ContentType.ToString().Should().Be(HeaderConstants.AtomicOperationsMediaType); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.AtomicOperations.ToString()); } [Fact] @@ -205,16 +159,16 @@ public async Task Prefers_JsonApi_with_relaxed_AtomicOperations_extension_in_Acc }; const string route = "/operations"; - const string contentType = HeaderConstants.AtomicOperationsMediaType; + string contentType = JsonApiMediaType.RelaxedAtomicOperations.ToString(); Action setRequestHeaders = headers => { headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("text/html")); - headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{HeaderConstants.MediaType}; profile=some")); - headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(HeaderConstants.MediaType)); - headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{HeaderConstants.MediaType}; unknown=unexpected")); - headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{HeaderConstants.MediaType};EXT=\"https://jsonapi.org/ext/atomic\"; q=0.2")); - headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{HeaderConstants.MediaType};EXT=atomic-operations; q=0.8")); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{JsonApiMediaType.Default}; profile=some")); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(JsonApiMediaType.Default.ToString())); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{JsonApiMediaType.Default}; unknown=unexpected")); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{JsonApiMediaType.Default};EXT=\"https://jsonapi.org/ext/atomic\"; q=0.8")); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{JsonApiMediaType.Default};EXT=atomic; q=0.2")); }; // Act @@ -223,8 +177,8 @@ public async Task Prefers_JsonApi_with_relaxed_AtomicOperations_extension_in_Acc // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - httpResponse.Content.Headers.ContentType.ShouldNotBeNull(); - httpResponse.Content.Headers.ContentType.ToString().Should().Be(HeaderConstants.RelaxedAtomicOperationsMediaType); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.RelaxedAtomicOperations.ToString()); } [Fact] @@ -236,10 +190,10 @@ public async Task Denies_JsonApi_with_parameters_in_Accept_headers() Action setRequestHeaders = headers => { headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("text/html")); - headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{HeaderConstants.MediaType}; profile=some")); - headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{HeaderConstants.MediaType}; ext=other")); - headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{HeaderConstants.MediaType}; unknown=unexpected")); - headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(HeaderConstants.AtomicOperationsMediaType)); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{JsonApiMediaType.Default}; profile=some")); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{JsonApiMediaType.Default}; ext=other")); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{JsonApiMediaType.Default}; unknown=unexpected")); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(JsonApiMediaType.AtomicOperations.ToString())); }; // Act @@ -248,13 +202,60 @@ public async Task Denies_JsonApi_with_parameters_in_Accept_headers() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotAcceptable); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotAcceptable); error.Title.Should().Be("The specified Accept header value does not contain any supported media types."); - error.Detail.Should().Be("Please include 'application/vnd.api+json' in the Accept header values."); - error.Source.ShouldNotBeNull(); + error.Detail.Should().Be($"Include '{JsonApiMediaType.Default}' in the Accept header values."); + error.Source.Should().NotBeNull(); + error.Source.Header.Should().Be("Accept"); + } + + [Fact] + public async Task Denies_no_Accept_headers_at_operations_endpoint() + { + // Arrange + var requestBody = new + { + atomic__operations = new[] + { + new + { + op = "add", + data = new + { + type = "policies", + attributes = new + { + name = "some" + } + } + } + } + }; + + const string route = "/operations"; + string contentType = JsonApiMediaType.AtomicOperations.ToString(); + + Action requestHeaders = _ => + { + }; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = + await _testContext.ExecutePostAsync(route, requestBody, contentType, requestHeaders); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotAcceptable); + + responseDocument.Errors.Should().HaveCount(1); + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.NotAcceptable); + error.Title.Should().Be("The specified Accept header value does not contain any supported media types."); + error.Detail.Should().Be($"Include '{JsonApiMediaType.AtomicOperations}' or '{JsonApiMediaType.RelaxedAtomicOperations}' in the Accept header values."); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be("Accept"); } @@ -282,9 +283,10 @@ public async Task Denies_JsonApi_in_Accept_headers_at_operations_endpoint() }; const string route = "/operations"; - const string contentType = HeaderConstants.AtomicOperationsMediaType; + string contentType = JsonApiMediaType.AtomicOperations.ToString(); - Action setRequestHeaders = headers => headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(HeaderConstants.MediaType)); + Action setRequestHeaders = headers => + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(JsonApiMediaType.Default.ToString())); // Act (HttpResponseMessage httpResponse, Document responseDocument) = @@ -293,16 +295,13 @@ public async Task Denies_JsonApi_in_Accept_headers_at_operations_endpoint() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotAcceptable); - responseDocument.Errors.ShouldHaveCount(1); - - const string detail = - $"Please include '{HeaderConstants.AtomicOperationsMediaType}' or '{HeaderConstants.RelaxedAtomicOperationsMediaType}' in the Accept header values."; + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotAcceptable); error.Title.Should().Be("The specified Accept header value does not contain any supported media types."); - error.Detail.Should().Be(detail); - error.Source.ShouldNotBeNull(); + error.Detail.Should().Be($"Include '{JsonApiMediaType.AtomicOperations}' or '{JsonApiMediaType.RelaxedAtomicOperations}' in the Accept header values."); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be("Accept"); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/ContentTypeHeaderTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/ContentTypeHeaderTests.cs index 4cabba7843..5627265ea6 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/ContentTypeHeaderTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/ContentTypeHeaderTests.cs @@ -1,4 +1,5 @@ using System.Net; +using System.Net.Http.Headers; using FluentAssertions; using JsonApiDotNetCore.Middleware; using JsonApiDotNetCore.Serialization.Objects; @@ -31,8 +32,8 @@ public async Task Returns_JsonApi_ContentType_header() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - httpResponse.Content.Headers.ContentType.ShouldNotBeNull(); - httpResponse.Content.Headers.ContentType.ToString().Should().Be(HeaderConstants.MediaType); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); } [Fact] @@ -66,8 +67,8 @@ public async Task Returns_JsonApi_ContentType_header_with_AtomicOperations_exten // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - httpResponse.Content.Headers.ContentType.ShouldNotBeNull(); - httpResponse.Content.Headers.ContentType.ToString().Should().Be(HeaderConstants.AtomicOperationsMediaType); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.AtomicOperations.ToString()); } [Fact] @@ -94,16 +95,19 @@ public async Task Returns_JsonApi_ContentType_header_with_relaxed_AtomicOperatio }; const string route = "/operations"; - const string contentType = HeaderConstants.RelaxedAtomicOperationsMediaType; + string contentType = JsonApiMediaType.RelaxedAtomicOperations.ToString(); + + Action setRequestHeaders = headers => + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(JsonApiMediaType.RelaxedAtomicOperations.ToString())); // Act - (HttpResponseMessage httpResponse, _) = await _testContext.ExecutePostAtomicAsync(route, requestBody, contentType); + (HttpResponseMessage httpResponse, _) = await _testContext.ExecutePostAsync(route, requestBody, contentType, setRequestHeaders); // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - httpResponse.Content.Headers.ContentType.ShouldNotBeNull(); - httpResponse.Content.Headers.ContentType.ToString().Should().Be(HeaderConstants.RelaxedAtomicOperationsMediaType); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.RelaxedAtomicOperations.ToString()); } [Fact] @@ -131,13 +135,64 @@ public async Task Denies_unknown_ContentType_header() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnsupportedMediaType); - responseDocument.Errors.ShouldHaveCount(1); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); + + responseDocument.Errors.Should().HaveCount(1); + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.UnsupportedMediaType); + error.Title.Should().Be("The specified Content-Type header value is not supported."); + error.Detail.Should().Be($"Use '{JsonApiMediaType.Default}' instead of 'text/html' for the Content-Type header value."); + error.Source.Should().NotBeNull(); + error.Source.Header.Should().Be("Content-Type"); + } + + [Fact] + public async Task Denies_unknown_ContentType_header_at_operations_endpoint() + { + // Arrange + var requestBody = new + { + atomic__operations = new[] + { + new + { + op = "add", + data = new + { + type = "policies", + attributes = new + { + name = "some" + } + } + } + } + }; + + const string route = "/operations"; + const string contentType = "text/html"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync(route, requestBody, contentType); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnsupportedMediaType); + + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); + + responseDocument.Errors.Should().HaveCount(1); + + string detail = + $"Use '{JsonApiMediaType.AtomicOperations}' or '{JsonApiMediaType.RelaxedAtomicOperations}' instead of 'text/html' for the Content-Type header value."; ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnsupportedMediaType); error.Title.Should().Be("The specified Content-Type header value is not supported."); - error.Detail.Should().Be("Please specify 'application/vnd.api+json' instead of 'text/html' for the Content-Type header value."); - error.Source.ShouldNotBeNull(); + error.Detail.Should().Be(detail); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be("Content-Type"); } @@ -158,14 +213,45 @@ public async Task Permits_JsonApi_ContentType_header() }; const string route = "/policies"; - const string contentType = HeaderConstants.MediaType; + string contentType = JsonApiMediaType.Default.ToString(); + + // Act + (HttpResponseMessage httpResponse, _) = await _testContext.ExecutePostAsync(route, requestBody, contentType); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); + + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); + } + + [Fact] + public async Task Permits_JsonApi_ContentType_header_in_upper_case() + { + // Arrange + var requestBody = new + { + data = new + { + type = "policies", + attributes = new + { + name = "some" + } + } + }; + + const string route = "/policies"; + string contentType = JsonApiMediaType.Default.ToString().ToUpperInvariant(); // Act - // ReSharper disable once RedundantArgumentDefaultValue (HttpResponseMessage httpResponse, _) = await _testContext.ExecutePostAsync(route, requestBody, contentType); // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); + + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); } [Fact] @@ -192,13 +278,63 @@ public async Task Permits_JsonApi_ContentType_header_with_AtomicOperations_exten }; const string route = "/operations"; - const string contentType = HeaderConstants.AtomicOperationsMediaType; // Act - (HttpResponseMessage httpResponse, _) = await _testContext.ExecutePostAsync(route, requestBody, contentType); + (HttpResponseMessage httpResponse, _) = await _testContext.ExecutePostAtomicAsync(route, requestBody); // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); + + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.AtomicOperations.ToString()); + } + + [Fact] + public async Task Denies_JsonApi_ContentType_header_with_AtomicOperations_extension_at_operations_endpoint_in_upper_case() + { + // Arrange + var requestBody = new + { + atomic__operations = new[] + { + new + { + op = "add", + data = new + { + type = "policies", + attributes = new + { + name = "some" + } + } + } + } + }; + + const string route = "/operations"; + string contentType = JsonApiMediaType.AtomicOperations.ToString().ToUpperInvariant(); + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync(route, requestBody, contentType); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnsupportedMediaType); + + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); + + responseDocument.Errors.Should().HaveCount(1); + + string detail = + $"Use '{JsonApiMediaType.AtomicOperations}' or '{JsonApiMediaType.RelaxedAtomicOperations}' instead of '{contentType}' for the Content-Type header value."; + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.UnsupportedMediaType); + error.Title.Should().Be("The specified Content-Type header value is not supported."); + error.Detail.Should().Be(detail); + error.Source.Should().NotBeNull(); + error.Source.Header.Should().Be("Content-Type"); } [Fact] @@ -225,17 +361,23 @@ public async Task Permits_JsonApi_ContentType_header_with_relaxed_AtomicOperatio }; const string route = "/operations"; - const string contentType = HeaderConstants.RelaxedAtomicOperationsMediaType; + string contentType = JsonApiMediaType.RelaxedAtomicOperations.ToString(); + + Action setRequestHeaders = headers => + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(JsonApiMediaType.RelaxedAtomicOperations.ToString())); // Act - (HttpResponseMessage httpResponse, _) = await _testContext.ExecutePostAsync(route, requestBody, contentType); + (HttpResponseMessage httpResponse, _) = await _testContext.ExecutePostAsync(route, requestBody, contentType, setRequestHeaders); // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); + + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.RelaxedAtomicOperations.ToString()); } [Fact] - public async Task Denies_JsonApi_ContentType_header_with_profile() + public async Task Denies_JsonApi_ContentType_header_with_unknown_extension() { // Arrange var requestBody = new @@ -251,7 +393,7 @@ public async Task Denies_JsonApi_ContentType_header_with_profile() }; const string route = "/policies"; - const string contentType = $"{HeaderConstants.MediaType}; profile=something"; + string contentType = $"{JsonApiMediaType.Default}; ext=something"; // Act (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync(route, requestBody, contentType); @@ -259,18 +401,21 @@ public async Task Denies_JsonApi_ContentType_header_with_profile() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnsupportedMediaType); - responseDocument.Errors.ShouldHaveCount(1); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); + + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnsupportedMediaType); error.Title.Should().Be("The specified Content-Type header value is not supported."); - error.Detail.Should().Be($"Please specify 'application/vnd.api+json' instead of '{contentType}' for the Content-Type header value."); - error.Source.ShouldNotBeNull(); + error.Detail.Should().Be($"Use '{JsonApiMediaType.Default}' instead of '{contentType}' for the Content-Type header value."); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be("Content-Type"); } [Fact] - public async Task Denies_JsonApi_ContentType_header_with_extension() + public async Task Denies_JsonApi_ContentType_header_with_AtomicOperations_extension_at_resource_endpoint() { // Arrange var requestBody = new @@ -286,7 +431,7 @@ public async Task Denies_JsonApi_ContentType_header_with_extension() }; const string route = "/policies"; - const string contentType = $"{HeaderConstants.MediaType}; ext=something"; + string contentType = JsonApiMediaType.AtomicOperations.ToString(); // Act (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync(route, requestBody, contentType); @@ -294,18 +439,21 @@ public async Task Denies_JsonApi_ContentType_header_with_extension() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnsupportedMediaType); - responseDocument.Errors.ShouldHaveCount(1); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); + + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnsupportedMediaType); error.Title.Should().Be("The specified Content-Type header value is not supported."); - error.Detail.Should().Be($"Please specify 'application/vnd.api+json' instead of '{contentType}' for the Content-Type header value."); - error.Source.ShouldNotBeNull(); + error.Detail.Should().Be($"Use '{JsonApiMediaType.Default}' instead of '{contentType}' for the Content-Type header value."); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be("Content-Type"); } [Fact] - public async Task Denies_JsonApi_ContentType_header_with_AtomicOperations_extension_at_resource_endpoint() + public async Task Denies_JsonApi_ContentType_header_with_relaxed_AtomicOperations_extension_at_resource_endpoint() { // Arrange var requestBody = new @@ -321,7 +469,7 @@ public async Task Denies_JsonApi_ContentType_header_with_AtomicOperations_extens }; const string route = "/policies"; - const string contentType = HeaderConstants.AtomicOperationsMediaType; + string contentType = JsonApiMediaType.RelaxedAtomicOperations.ToString(); // Act (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync(route, requestBody, contentType); @@ -329,18 +477,21 @@ public async Task Denies_JsonApi_ContentType_header_with_AtomicOperations_extens // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnsupportedMediaType); - responseDocument.Errors.ShouldHaveCount(1); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); + + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnsupportedMediaType); error.Title.Should().Be("The specified Content-Type header value is not supported."); - error.Detail.Should().Be($"Please specify 'application/vnd.api+json' instead of '{contentType}' for the Content-Type header value."); - error.Source.ShouldNotBeNull(); + error.Detail.Should().Be($"Use '{JsonApiMediaType.Default}' instead of '{contentType}' for the Content-Type header value."); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be("Content-Type"); } [Fact] - public async Task Denies_JsonApi_ContentType_header_with_relaxed_AtomicOperations_extension_at_resource_endpoint() + public async Task Denies_JsonApi_ContentType_header_with_profile() { // Arrange var requestBody = new @@ -356,7 +507,7 @@ public async Task Denies_JsonApi_ContentType_header_with_relaxed_AtomicOperation }; const string route = "/policies"; - const string contentType = HeaderConstants.RelaxedAtomicOperationsMediaType; + string contentType = $"{JsonApiMediaType.Default}; profile=something"; // Act (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync(route, requestBody, contentType); @@ -364,13 +515,16 @@ public async Task Denies_JsonApi_ContentType_header_with_relaxed_AtomicOperation // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnsupportedMediaType); - responseDocument.Errors.ShouldHaveCount(1); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); + + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnsupportedMediaType); error.Title.Should().Be("The specified Content-Type header value is not supported."); - error.Detail.Should().Be($"Please specify 'application/vnd.api+json' instead of '{contentType}' for the Content-Type header value."); - error.Source.ShouldNotBeNull(); + error.Detail.Should().Be($"Use '{JsonApiMediaType.Default}' instead of '{contentType}' for the Content-Type header value."); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be("Content-Type"); } @@ -391,7 +545,7 @@ public async Task Denies_JsonApi_ContentType_header_with_CharSet() }; const string route = "/policies"; - const string contentType = $"{HeaderConstants.MediaType}; charset=ISO-8859-4"; + string contentType = $"{JsonApiMediaType.Default}; charset=ISO-8859-4"; // Act (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync(route, requestBody, contentType); @@ -399,13 +553,16 @@ public async Task Denies_JsonApi_ContentType_header_with_CharSet() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnsupportedMediaType); - responseDocument.Errors.ShouldHaveCount(1); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); + + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnsupportedMediaType); error.Title.Should().Be("The specified Content-Type header value is not supported."); - error.Detail.Should().Be($"Please specify 'application/vnd.api+json' instead of '{contentType}' for the Content-Type header value."); - error.Source.ShouldNotBeNull(); + error.Detail.Should().Be($"Use '{JsonApiMediaType.Default}' instead of '{contentType}' for the Content-Type header value."); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be("Content-Type"); } @@ -426,7 +583,7 @@ public async Task Denies_JsonApi_ContentType_header_with_unknown_parameter() }; const string route = "/policies"; - const string contentType = $"{HeaderConstants.MediaType}; unknown=unexpected"; + string contentType = $"{JsonApiMediaType.Default}; unknown=unexpected"; // Act (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync(route, requestBody, contentType); @@ -434,13 +591,16 @@ public async Task Denies_JsonApi_ContentType_header_with_unknown_parameter() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnsupportedMediaType); - responseDocument.Errors.ShouldHaveCount(1); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); + + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnsupportedMediaType); error.Title.Should().Be("The specified Content-Type header value is not supported."); - error.Detail.Should().Be($"Please specify 'application/vnd.api+json' instead of '{contentType}' for the Content-Type header value."); - error.Source.ShouldNotBeNull(); + error.Detail.Should().Be($"Use '{JsonApiMediaType.Default}' instead of '{contentType}' for the Content-Type header value."); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be("Content-Type"); } @@ -468,25 +628,27 @@ public async Task Denies_JsonApi_ContentType_header_at_operations_endpoint() }; const string route = "/operations"; - const string contentType = HeaderConstants.MediaType; + string contentType = JsonApiMediaType.Default.ToString(); // Act - // ReSharper disable once RedundantArgumentDefaultValue (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync(route, requestBody, contentType); // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnsupportedMediaType); - responseDocument.Errors.ShouldHaveCount(1); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); + + responseDocument.Errors.Should().HaveCount(1); - const string detail = - $"Please specify '{HeaderConstants.AtomicOperationsMediaType}' or '{HeaderConstants.RelaxedAtomicOperationsMediaType}' instead of '{contentType}' for the Content-Type header value."; + string detail = + $"Use '{JsonApiMediaType.AtomicOperations}' or '{JsonApiMediaType.RelaxedAtomicOperations}' instead of '{contentType}' for the Content-Type header value."; ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnsupportedMediaType); error.Title.Should().Be("The specified Content-Type header value is not supported."); error.Detail.Should().Be(detail); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be("Content-Type"); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/CapturingDocumentAdapter.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/CapturingDocumentAdapter.cs new file mode 100644 index 0000000000..fc138415b3 --- /dev/null +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/CapturingDocumentAdapter.cs @@ -0,0 +1,25 @@ +using JsonApiDotNetCore.Serialization.Objects; +using JsonApiDotNetCore.Serialization.Request.Adapters; + +namespace JsonApiDotNetCoreTests.IntegrationTests.ContentNegotiation.CustomExtensions; + +internal sealed class CapturingDocumentAdapter : IDocumentAdapter +{ + private readonly IDocumentAdapter _innerAdapter; + private readonly RequestDocumentStore _requestDocumentStore; + + public CapturingDocumentAdapter(IDocumentAdapter innerAdapter, RequestDocumentStore requestDocumentStore) + { + ArgumentNullException.ThrowIfNull(innerAdapter); + ArgumentNullException.ThrowIfNull(requestDocumentStore); + + _innerAdapter = innerAdapter; + _requestDocumentStore = requestDocumentStore; + } + + public object? Convert(Document document) + { + _requestDocumentStore.Document = document; + return _innerAdapter.Convert(document); + } +} diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/CustomExtensionsAcceptHeaderTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/CustomExtensionsAcceptHeaderTests.cs new file mode 100644 index 0000000000..d1c859aaea --- /dev/null +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/CustomExtensionsAcceptHeaderTests.cs @@ -0,0 +1,156 @@ +using System.Net; +using System.Net.Http.Headers; +using FluentAssertions; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.Serialization.Objects; +using JsonApiDotNetCore.Serialization.Response; +using Microsoft.Extensions.DependencyInjection; +using TestBuildingBlocks; +using Xunit; + +namespace JsonApiDotNetCoreTests.IntegrationTests.ContentNegotiation.CustomExtensions; + +public sealed class CustomExtensionsAcceptHeaderTests : IClassFixture, PolicyDbContext>> +{ + private readonly IntegrationTestContext, PolicyDbContext> _testContext; + + public CustomExtensionsAcceptHeaderTests(IntegrationTestContext, PolicyDbContext> testContext) + { + _testContext = testContext; + + testContext.UseController(); + testContext.UseController(); + + testContext.ConfigureServices(services => + { + services.AddSingleton(); + services.AddScoped(); + services.AddScoped(); + }); + + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.IncludeExtensions(ServerTimeMediaTypeExtension.ServerTime, ServerTimeMediaTypeExtension.RelaxedServerTime); + } + + [Fact] + public async Task Permits_JsonApi_without_parameters_in_Accept_headers() + { + // Arrange + const string route = "/policies"; + + Action setRequestHeaders = headers => + { + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("text/html")); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{JsonApiMediaType.Default}; profile=some")); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{JsonApiMediaType.Default}; ext=other")); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{JsonApiMediaType.Default}; unknown=unexpected")); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{JsonApiMediaType.Default}; q=0.3")); + }; + + // Act + (HttpResponseMessage httpResponse, _) = await _testContext.ExecuteGetAsync(route, setRequestHeaders); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); + + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); + } + + [Fact] + public async Task Prefers_first_match_from_GetPossibleMediaTypes_with_largest_number_of_extensions() + { + // Arrange + const string route = "/policies"; + + Action setRequestHeaders = headers => + { + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("text/html")); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(JsonApiMediaType.Default.ToString())); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(ServerTimeMediaTypes.RelaxedServerTime.ToString())); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(ServerTimeMediaTypes.ServerTime.ToString())); + }; + + // Act + (HttpResponseMessage httpResponse, _) = await _testContext.ExecuteGetAsync(route, setRequestHeaders); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); + + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(ServerTimeMediaTypes.ServerTime.ToString()); + } + + [Fact] + public async Task Prefers_quality_factor_over_largest_number_of_extensions() + { + // Arrange + const string route = "/policies"; + + Action setRequestHeaders = headers => + { + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("text/html")); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{ServerTimeMediaTypes.ServerTime}; q=0.2")); + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse($"{JsonApiMediaType.Default}; q=0.8")); + }; + + // Act + (HttpResponseMessage httpResponse, _) = await _testContext.ExecuteGetAsync(route, setRequestHeaders); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); + + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); + } + + [Fact] + public async Task Denies_extensions_mismatch_between_ContentType_and_Accept_header() + { + // Arrange + var requestBody = new + { + atomic__operations = new[] + { + new + { + op = "add", + data = new + { + type = "policies", + attributes = new + { + name = "some" + } + } + } + } + }; + + const string route = "/operations"; + string contentType = ServerTimeMediaTypes.AtomicOperationsWithServerTime.ToString(); + + Action setRequestHeaders = headers => + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(JsonApiMediaType.AtomicOperations.ToString())); + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = + await _testContext.ExecutePostAsync(route, requestBody, contentType, setRequestHeaders); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotAcceptable); + + responseDocument.Errors.Should().HaveCount(1); + + string detail = $"Include '{JsonApiMediaType.AtomicOperations}' or '{ServerTimeMediaTypes.AtomicOperationsWithServerTime}' or " + + $"'{JsonApiMediaType.RelaxedAtomicOperations}' or '{ServerTimeMediaTypes.RelaxedAtomicOperationsWithRelaxedServerTime}' in the Accept header values."; + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.NotAcceptable); + error.Title.Should().Be("The specified Accept header value does not contain any supported media types."); + error.Detail.Should().Be(detail); + error.Source.Should().NotBeNull(); + error.Source.Header.Should().Be("Accept"); + } +} diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/CustomExtensionsContentTypeTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/CustomExtensionsContentTypeTests.cs new file mode 100644 index 0000000000..261f7b5149 --- /dev/null +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/CustomExtensionsContentTypeTests.cs @@ -0,0 +1,336 @@ +using System.Net; +using System.Net.Http.Headers; +using FluentAssertions; +using FluentAssertions.Extensions; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.Serialization.Objects; +using JsonApiDotNetCore.Serialization.Request.Adapters; +using JsonApiDotNetCore.Serialization.Response; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using TestBuildingBlocks; +using Xunit; + +namespace JsonApiDotNetCoreTests.IntegrationTests.ContentNegotiation.CustomExtensions; + +public sealed class CustomExtensionsContentTypeTests : IClassFixture, PolicyDbContext>> +{ + private static readonly DateTimeOffset CurrentTime = 31.December(2024).At(21, 53, 40).AsUtc(); + private readonly IntegrationTestContext, PolicyDbContext> _testContext; + + public CustomExtensionsContentTypeTests(IntegrationTestContext, PolicyDbContext> testContext) + { + _testContext = testContext; + + testContext.UseController(); + testContext.UseController(); + + testContext.ConfigureServices(services => + { + services.AddSingleton(); + services.AddScoped(); + + services.AddScoped(); + services.AddScoped(); + + services.AddScoped(serviceProvider => + { + var documentAdapter = serviceProvider.GetRequiredService(); + var requestDocumentStore = serviceProvider.GetRequiredService(); + return new CapturingDocumentAdapter(documentAdapter, requestDocumentStore); + }); + }); + + testContext.PostConfigureServices(services => services.Replace( + ServiceDescriptor.Singleton(new FrozenTimeProvider(CurrentTime, TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time"))))); + + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.IncludeExtensions(ServerTimeMediaTypeExtension.ServerTime, ServerTimeMediaTypeExtension.RelaxedServerTime); + } + + [Fact] + public async Task Permits_JsonApi_ContentType_header() + { + // Arrange + var requestBody = new + { + data = new + { + type = "policies", + attributes = new + { + name = "some" + } + } + }; + + const string route = "/policies"; + string contentType = JsonApiMediaType.Default.ToString(); + + // Act + (HttpResponseMessage httpResponse, _) = await _testContext.ExecutePostAsync(route, requestBody, contentType); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); + + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); + } + + [Fact] + public async Task Permits_JsonApi_ContentType_header_with_ServerTime_extension() + { + // Arrange + var requestBody = new + { + meta = new + { + useLocalTime = true + }, + data = new + { + type = "policies", + attributes = new + { + name = "some" + } + } + }; + + const string route = "/policies"; + string contentType = ServerTimeMediaTypes.ServerTime.ToString(); + + Action setRequestHeaders = headers => + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(ServerTimeMediaTypes.ServerTime.ToString())); + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = + await _testContext.ExecutePostAsync(route, requestBody, contentType, setRequestHeaders); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); + + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(ServerTimeMediaTypes.ServerTime.ToString()); + + responseDocument.Meta.Should().ContainKey("localServerTime").WhoseValue.Should().NotBeNull().And.Subject.ToString().Should() + .Be("2025-01-01T06:53:40.0000000+09:00"); + } + + [Fact] + public async Task Permits_JsonApi_ContentType_header_with_relaxed_ServerTime_extension() + { + // Arrange + var requestBody = new + { + data = new + { + type = "policies", + attributes = new + { + name = "some" + } + } + }; + + const string route = "/policies"; + string contentType = ServerTimeMediaTypes.RelaxedServerTime.ToString(); + + Action setRequestHeaders = headers => + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(ServerTimeMediaTypes.RelaxedServerTime.ToString())); + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = + await _testContext.ExecutePostAsync(route, requestBody, contentType, setRequestHeaders); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); + + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(ServerTimeMediaTypes.RelaxedServerTime.ToString()); + + responseDocument.Meta.Should().ContainKey("utcServerTime").WhoseValue.Should().NotBeNull().And.Subject.ToString().Should() + .Be("2024-12-31T21:53:40.0000000Z"); + } + + [Fact] + public async Task Permits_JsonApi_ContentType_header_with_AtomicOperations_and_ServerTime_extension_at_operations_endpoint() + { + // Arrange + var requestBody = new + { + atomic__operations = new[] + { + new + { + op = "add", + data = new + { + type = "policies", + attributes = new + { + name = "some" + } + } + } + } + }; + + const string route = "/operations"; + string contentType = ServerTimeMediaTypes.AtomicOperationsWithServerTime.ToString(); + + Action setRequestHeaders = headers => + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(ServerTimeMediaTypes.AtomicOperationsWithServerTime.ToString())); + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = + await _testContext.ExecutePostAsync(route, requestBody, contentType, setRequestHeaders); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); + + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(ServerTimeMediaTypes.AtomicOperationsWithServerTime.ToString()); + + responseDocument.Meta.Should().ContainKey("utcServerTime").WhoseValue.Should().NotBeNull().And.Subject.ToString().Should() + .Be("2024-12-31T21:53:40.0000000Z"); + } + + [Fact] + public async Task Permits_JsonApi_ContentType_header_with_relaxed_AtomicOperations_and_relaxed_ServerTime_extension_at_operations_endpoint() + { + // Arrange + var requestBody = new + { + meta = new + { + useLocalTime = true + }, + + atomic__operations = new[] + { + new + { + op = "add", + data = new + { + type = "policies", + attributes = new + { + name = "some" + } + } + } + } + }; + + const string route = "/operations"; + string contentType = ServerTimeMediaTypes.RelaxedAtomicOperationsWithRelaxedServerTime.ToString(); + + Action setRequestHeaders = headers => + headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(ServerTimeMediaTypes.RelaxedAtomicOperationsWithRelaxedServerTime.ToString())); + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = + await _testContext.ExecutePostAsync(route, requestBody, contentType, setRequestHeaders); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); + + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(ServerTimeMediaTypes.RelaxedAtomicOperationsWithRelaxedServerTime.ToString()); + + responseDocument.Meta.Should().ContainKey("localServerTime"); + } + + [Fact] + public async Task Denies_JsonApi_ContentType_header_with_AtomicOperations_extension_and_ServerTime_at_resource_endpoint() + { + // Arrange + var requestBody = new + { + data = new + { + type = "policies", + attributes = new + { + name = "some" + } + } + }; + + const string route = "/policies"; + string contentType = ServerTimeMediaTypes.AtomicOperationsWithServerTime.ToString(); + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync(route, requestBody, contentType); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnsupportedMediaType); + + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); + + responseDocument.Errors.Should().HaveCount(1); + + string detail = $"Use '{JsonApiMediaType.Default}' or '{ServerTimeMediaTypes.ServerTime}' or " + + $"'{ServerTimeMediaTypes.RelaxedServerTime}' instead of '{contentType}' for the Content-Type header value."; + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.UnsupportedMediaType); + error.Title.Should().Be("The specified Content-Type header value is not supported."); + error.Detail.Should().Be(detail); + error.Source.Should().NotBeNull(); + error.Source.Header.Should().Be("Content-Type"); + } + + [Fact] + public async Task Denies_JsonApi_ContentType_header_with_relaxed_ServerTime_at_operations_endpoint() + { + // Arrange + var requestBody = new + { + atomic__operations = new[] + { + new + { + op = "add", + data = new + { + type = "policies", + attributes = new + { + name = "some" + } + } + } + } + }; + + const string route = "/operations"; + string contentType = ServerTimeMediaTypes.RelaxedServerTime.ToString(); + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync(route, requestBody, contentType); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnsupportedMediaType); + + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); + + responseDocument.Errors.Should().HaveCount(1); + + string detail = $"Use '{JsonApiMediaType.AtomicOperations}' or '{ServerTimeMediaTypes.AtomicOperationsWithServerTime}' or " + + $"'{JsonApiMediaType.RelaxedAtomicOperations}' or '{ServerTimeMediaTypes.RelaxedAtomicOperationsWithRelaxedServerTime}' " + + $"instead of '{contentType}' for the Content-Type header value."; + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.UnsupportedMediaType); + error.Title.Should().Be("The specified Content-Type header value is not supported."); + error.Detail.Should().Be(detail); + error.Source.Should().NotBeNull(); + error.Source.Header.Should().Be("Content-Type"); + } +} diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/RequestDocumentStore.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/RequestDocumentStore.cs new file mode 100644 index 0000000000..e972cdd078 --- /dev/null +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/RequestDocumentStore.cs @@ -0,0 +1,8 @@ +using JsonApiDotNetCore.Serialization.Objects; + +namespace JsonApiDotNetCoreTests.IntegrationTests.ContentNegotiation.CustomExtensions; + +internal sealed class RequestDocumentStore +{ + public Document? Document { get; set; } +} diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/ServerTimeContentNegotiator.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/ServerTimeContentNegotiator.cs new file mode 100644 index 0000000000..e6e507e2b2 --- /dev/null +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/ServerTimeContentNegotiator.cs @@ -0,0 +1,59 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Middleware; +using Microsoft.AspNetCore.Http; + +namespace JsonApiDotNetCoreTests.IntegrationTests.ContentNegotiation.CustomExtensions; + +internal sealed class ServerTimeContentNegotiator(IJsonApiOptions options, IHttpContextAccessor httpContextAccessor) + : JsonApiContentNegotiator(options, httpContextAccessor) +{ + private readonly IJsonApiOptions _options = options; + + protected override IReadOnlyList GetPossibleMediaTypes() + { + List mediaTypes = []; + + // Relaxed entries come after JSON:API compliant entries, which makes them less likely to be selected. + + if (IsOperationsEndpoint()) + { + if (_options.Extensions.Contains(JsonApiMediaTypeExtension.AtomicOperations)) + { + mediaTypes.Add(JsonApiMediaType.AtomicOperations); + } + + if (_options.Extensions.Contains(JsonApiMediaTypeExtension.AtomicOperations) && + _options.Extensions.Contains(ServerTimeMediaTypeExtension.ServerTime)) + { + mediaTypes.Add(ServerTimeMediaTypes.AtomicOperationsWithServerTime); + } + + if (_options.Extensions.Contains(JsonApiMediaTypeExtension.RelaxedAtomicOperations)) + { + mediaTypes.Add(JsonApiMediaType.RelaxedAtomicOperations); + } + + if (_options.Extensions.Contains(JsonApiMediaTypeExtension.RelaxedAtomicOperations) && + _options.Extensions.Contains(ServerTimeMediaTypeExtension.RelaxedServerTime)) + { + mediaTypes.Add(ServerTimeMediaTypes.RelaxedAtomicOperationsWithRelaxedServerTime); + } + } + else + { + mediaTypes.Add(JsonApiMediaType.Default); + + if (_options.Extensions.Contains(ServerTimeMediaTypeExtension.ServerTime)) + { + mediaTypes.Add(ServerTimeMediaTypes.ServerTime); + } + + if (_options.Extensions.Contains(ServerTimeMediaTypeExtension.RelaxedServerTime)) + { + mediaTypes.Add(ServerTimeMediaTypes.RelaxedServerTime); + } + } + + return mediaTypes.AsReadOnly(); + } +} diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/ServerTimeMediaTypeExtension.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/ServerTimeMediaTypeExtension.cs new file mode 100644 index 0000000000..35756e99a8 --- /dev/null +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/ServerTimeMediaTypeExtension.cs @@ -0,0 +1,11 @@ +using JsonApiDotNetCore.Middleware; + +#pragma warning disable AV1008 // Class should not be static + +namespace JsonApiDotNetCoreTests.IntegrationTests.ContentNegotiation.CustomExtensions; + +internal static class ServerTimeMediaTypeExtension +{ + public static readonly JsonApiMediaTypeExtension ServerTime = new("https://www.jsonapi.net/ext/server-time"); + public static readonly JsonApiMediaTypeExtension RelaxedServerTime = new("server-time"); +} diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/ServerTimeMediaTypes.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/ServerTimeMediaTypes.cs new file mode 100644 index 0000000000..8fd5f0d377 --- /dev/null +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/ServerTimeMediaTypes.cs @@ -0,0 +1,21 @@ +using JsonApiDotNetCore.Middleware; + +#pragma warning disable AV1008 // Class should not be static + +namespace JsonApiDotNetCoreTests.IntegrationTests.ContentNegotiation.CustomExtensions; + +internal static class ServerTimeMediaTypes +{ + public static readonly JsonApiMediaType ServerTime = new([ServerTimeMediaTypeExtension.ServerTime]); + public static readonly JsonApiMediaType RelaxedServerTime = new([ServerTimeMediaTypeExtension.RelaxedServerTime]); + + public static readonly JsonApiMediaType AtomicOperationsWithServerTime = new([ + JsonApiMediaTypeExtension.AtomicOperations, + ServerTimeMediaTypeExtension.ServerTime + ]); + + public static readonly JsonApiMediaType RelaxedAtomicOperationsWithRelaxedServerTime = new([ + JsonApiMediaTypeExtension.RelaxedAtomicOperations, + ServerTimeMediaTypeExtension.RelaxedServerTime + ]); +} diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/ServerTimeResponseMeta.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/ServerTimeResponseMeta.cs new file mode 100644 index 0000000000..27487e0149 --- /dev/null +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/CustomExtensions/ServerTimeResponseMeta.cs @@ -0,0 +1,37 @@ +using System.Globalization; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.Serialization.Response; + +namespace JsonApiDotNetCoreTests.IntegrationTests.ContentNegotiation.CustomExtensions; + +internal sealed class ServerTimeResponseMeta(IJsonApiRequest request, RequestDocumentStore documentStore, TimeProvider timeProvider) : IResponseMeta +{ + private readonly IJsonApiRequest _request = request; + private readonly RequestDocumentStore _documentStore = documentStore; + private readonly TimeProvider _timeProvider = timeProvider; + + public IDictionary? GetMeta() + { + if (_request.Extensions.Contains(ServerTimeMediaTypeExtension.ServerTime) || + _request.Extensions.Contains(ServerTimeMediaTypeExtension.RelaxedServerTime)) + { + if (_documentStore.Document is not { Meta: not null } || !_documentStore.Document.Meta.TryGetValue("useLocalTime", out object? useLocalTimeValue) || + useLocalTimeValue == null || !bool.TryParse(useLocalTimeValue.ToString(), out bool useLocalTime)) + { + useLocalTime = false; + } + + return useLocalTime + ? new Dictionary + { + ["localServerTime"] = _timeProvider.GetLocalNow().ToString("O", CultureInfo.InvariantCulture) + } + : new Dictionary + { + ["utcServerTime"] = _timeProvider.GetUtcNow().UtcDateTime.ToString("O", CultureInfo.InvariantCulture) + }; + } + + return null; + } +} diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/OperationsController.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/OperationsController.cs index 24300dfc5c..9792ed8830 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/OperationsController.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/OperationsController.cs @@ -9,5 +9,5 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ContentNegotiation; public sealed class OperationsController( IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, IOperationsProcessor processor, IJsonApiRequest request, - ITargetedFields targetedFields, IAtomicOperationFilter operationFilter) : JsonApiOperationsController(options, resourceGraph, loggerFactory, processor, - request, targetedFields, operationFilter); + ITargetedFields targetedFields, IAtomicOperationFilter operationFilter) + : JsonApiOperationsController(options, resourceGraph, loggerFactory, processor, request, targetedFields, operationFilter); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/PolicyDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/PolicyDbContext.cs index bf96700a06..94f44189cf 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/PolicyDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ContentNegotiation/PolicyDbContext.cs @@ -5,7 +5,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ContentNegotiation; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class PolicyDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class PolicyDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet Policies => Set(); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ControllerActionResults/ActionResultDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ControllerActionResults/ActionResultDbContext.cs index bbf27df0d3..6d3e9e654a 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ControllerActionResults/ActionResultDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ControllerActionResults/ActionResultDbContext.cs @@ -5,7 +5,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ControllerActionResults; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class ActionResultDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class ActionResultDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet Toothbrushes => Set(); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ControllerActionResults/ActionResultTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ControllerActionResults/ActionResultTests.cs index b11c31623c..fe047449f1 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ControllerActionResults/ActionResultTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ControllerActionResults/ActionResultTests.cs @@ -37,7 +37,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(toothbrush.StringId); } @@ -53,7 +53,7 @@ public async Task Converts_empty_ActionResult_to_error_collection() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -73,7 +73,7 @@ public async Task Converts_ActionResult_with_error_object_to_error_collection() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -93,7 +93,7 @@ public async Task Cannot_convert_ActionResult_with_string_parameter_to_error_col // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.InternalServerError); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.InternalServerError); @@ -113,7 +113,7 @@ public async Task Converts_ObjectResult_with_error_object_to_error_collection() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadGateway); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadGateway); @@ -133,7 +133,7 @@ public async Task Converts_ObjectResult_with_error_objects_to_error_collection() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(3); + responseDocument.Errors.Should().HaveCount(3); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.PreconditionFailed); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/ApiControllerAttributeLogTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/ApiControllerAttributeLogTests.cs index 5a83599a3a..132fa446b1 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/ApiControllerAttributeLogTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/ApiControllerAttributeLogTests.cs @@ -6,39 +6,49 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.CustomRoutes; -public sealed class ApiControllerAttributeLogTests : IntegrationTestContext, CustomRouteDbContext> +public sealed class ApiControllerAttributeLogTests : IntegrationTestContext, CustomRouteDbContext>, IAsyncDisposable { - private readonly FakeLoggerFactory _loggerFactory; + private readonly CapturingLoggerProvider _loggerProvider; public ApiControllerAttributeLogTests() { UseController(); - _loggerFactory = new FakeLoggerFactory(LogLevel.Warning); + _loggerProvider = new CapturingLoggerProvider(LogLevel.Warning); ConfigureLogging(options => { - options.ClearProviders(); - options.AddProvider(_loggerFactory); - }); + options.AddProvider(_loggerProvider); - ConfigureServices(services => services.AddSingleton(_loggerFactory)); + options.Services.AddSingleton(_loggerProvider); + }); } [Fact] public void Logs_warning_at_startup_when_ApiControllerAttribute_found() { // Arrange - _loggerFactory.Logger.Clear(); + _loggerProvider.Clear(); // Act _ = Factory; // Assert - IReadOnlyList logLines = _loggerFactory.Logger.GetLines(); - logLines.ShouldHaveCount(1); + IReadOnlyList logLines = _loggerProvider.GetLines(); + logLines.Should().HaveCount(1); logLines[0].Should().Be( $"[WARNING] Found JSON:API controller '{typeof(CiviliansController)}' with [ApiController]. Please remove this attribute for optimal JSON:API compliance."); } + + public override Task DisposeAsync() + { + _loggerProvider.Dispose(); + return base.DisposeAsync(); + } + + async ValueTask IAsyncDisposable.DisposeAsync() + { + await DisposeAsync(); + } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/ApiControllerAttributeTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/ApiControllerAttributeTests.cs index a27ef77329..731401137b 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/ApiControllerAttributeTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/ApiControllerAttributeTests.cs @@ -29,10 +29,10 @@ public async Task ApiController_attribute_transforms_NotFound_action_result_with // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; - error.Links.ShouldNotBeNull(); + error.Links.Should().NotBeNull(); error.Links.About.Should().StartWith("https://tools.ietf.org/html/rfc"); } @@ -61,11 +61,11 @@ public async Task ProblemDetails_from_invalid_ModelState_is_translated_into_erro // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(2); + responseDocument.Errors.Should().HaveCount(2); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.BadRequest); - error1.Links.ShouldNotBeNull(); + error1.Links.Should().NotBeNull(); error1.Links.About.Should().StartWith("https://tools.ietf.org/html/rfc"); error1.Title.Should().Be("One or more validation errors occurred."); error1.Detail.Should().Be("The Name field is required."); @@ -73,7 +73,7 @@ public async Task ProblemDetails_from_invalid_ModelState_is_translated_into_erro ErrorObject error2 = responseDocument.Errors[1]; error2.StatusCode.Should().Be(HttpStatusCode.BadRequest); - error2.Links.ShouldNotBeNull(); + error2.Links.Should().NotBeNull(); error2.Links.About.Should().StartWith("https://tools.ietf.org/html/rfc"); error2.Title.Should().Be("One or more validation errors occurred."); error2.Detail.Should().Be("The field YearOfBirth must be between 1900 and 2050."); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/CustomRouteDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/CustomRouteDbContext.cs index 43c3bfa59f..2228b1e304 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/CustomRouteDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/CustomRouteDbContext.cs @@ -5,7 +5,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.CustomRoutes; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class CustomRouteDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class CustomRouteDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet Towns => Set(); public DbSet Civilians => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/CustomRouteTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/CustomRouteTests.cs index e89641470d..eb74e50fb4 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/CustomRouteTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/CustomRouteTests.cs @@ -25,8 +25,8 @@ public CustomRouteTests(IntegrationTestContext { @@ -42,24 +42,24 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("towns"); responseDocument.Data.SingleValue.Id.Should().Be(town.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("name").With(value => value.Should().Be(town.Name)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("latitude").With(value => value.Should().Be(town.Latitude)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("longitude").With(value => value.Should().Be(town.Longitude)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(town.Name); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("latitude").WhoseValue.Should().Be(town.Latitude); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("longitude").WhoseValue.Should().Be(town.Longitude); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("civilians").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("civilians").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{HostPrefix}{route}/relationships/civilians"); value.Links.Related.Should().Be($"{HostPrefix}{route}/civilians"); }); - responseDocument.Data.SingleValue.Links.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Links.Should().NotBeNull(); responseDocument.Data.SingleValue.Links.Self.Should().Be($"{HostPrefix}{route}"); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); } @@ -67,7 +67,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_resources_at_custom_action_method() { // Arrange - List towns = _fakers.Town.Generate(7); + List towns = _fakers.Town.GenerateList(7); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -84,9 +84,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(5); - responseDocument.Data.ManyValue.Should().OnlyContain(resourceObject => resourceObject.Type == "towns"); - responseDocument.Data.ManyValue.Should().OnlyContain(resourceObject => resourceObject.Attributes.ShouldNotBeNull().Any()); - responseDocument.Data.ManyValue.Should().OnlyContain(resourceObject => resourceObject.Relationships.ShouldNotBeNull().Any()); + responseDocument.Data.ManyValue.Should().HaveCount(5); + responseDocument.Data.ManyValue.Should().OnlyContain(resource => resource.Type == "towns"); + responseDocument.Data.ManyValue.Should().OnlyContain(resource => resource.Attributes != null && resource.Attributes.Count > 0); + responseDocument.Data.ManyValue.Should().OnlyContain(resource => resource.Relationships != null && resource.Relationships.Count > 0); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/BuildingDefinition.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/BuildingDefinition.cs index 18dca5a502..dbdfea8a6f 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/BuildingDefinition.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/BuildingDefinition.cs @@ -1,5 +1,4 @@ using JetBrains.Annotations; -using JsonApiDotNetCore; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Middleware; using JsonApiDotNetCore.Resources; @@ -14,7 +13,7 @@ public sealed class BuildingDefinition : JsonApiResourceDefinition options) : TestableDbContext(options) +public sealed class EagerLoadingDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet States => Set(); public DbSet Streets => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/EagerLoadingTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/EagerLoadingTests.cs index f12123c203..8b64dfcbbf 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/EagerLoadingTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/EagerLoadingTests.cs @@ -32,10 +32,10 @@ public EagerLoadingTests(IntegrationTestContext { @@ -51,27 +51,27 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(building.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("number").With(value => value.Should().Be(building.Number)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("windowCount").With(value => value.Should().Be(4)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("primaryDoorColor").With(value => value.Should().Be(building.PrimaryDoor.Color)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("secondaryDoorColor").With(value => value.Should().Be(building.SecondaryDoor.Color)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("number").WhoseValue.Should().Be(building.Number); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("windowCount").WhoseValue.Should().Be(4); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("primaryDoorColor").WhoseValue.Should().Be(building.PrimaryDoor.Color); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("secondaryDoorColor").WhoseValue.Should().Be(building.SecondaryDoor.Color); } [Fact] public async Task Can_get_primary_resource_with_nested_eager_loads() { // Arrange - Street street = _fakers.Street.Generate(); - street.Buildings = _fakers.Building.Generate(2); + Street street = _fakers.Street.GenerateOne(); + street.Buildings = _fakers.Building.GenerateList(2); - street.Buildings[0].Windows = _fakers.Window.Generate(2); - street.Buildings[0].PrimaryDoor = _fakers.Door.Generate(); + street.Buildings[0].Windows = _fakers.Window.GenerateList(2); + street.Buildings[0].PrimaryDoor = _fakers.Door.GenerateOne(); - street.Buildings[1].Windows = _fakers.Window.Generate(3); - street.Buildings[1].PrimaryDoor = _fakers.Door.Generate(); - street.Buildings[1].SecondaryDoor = _fakers.Door.Generate(); + street.Buildings[1].Windows = _fakers.Window.GenerateList(3); + street.Buildings[1].PrimaryDoor = _fakers.Door.GenerateOne(); + street.Buildings[1].SecondaryDoor = _fakers.Door.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -87,22 +87,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(street.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("name").With(value => value.Should().Be(street.Name)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("buildingCount").With(value => value.Should().Be(2)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("doorTotalCount").With(value => value.Should().Be(3)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("windowTotalCount").With(value => value.Should().Be(5)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(street.Name); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("buildingCount").WhoseValue.Should().Be(2); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("doorTotalCount").WhoseValue.Should().Be(3); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("windowTotalCount").WhoseValue.Should().Be(5); } [Fact] public async Task Can_get_primary_resource_with_fieldset() { // Arrange - Street street = _fakers.Street.Generate(); - street.Buildings = _fakers.Building.Generate(1); - street.Buildings[0].Windows = _fakers.Window.Generate(3); - street.Buildings[0].PrimaryDoor = _fakers.Door.Generate(); + Street street = _fakers.Street.GenerateOne(); + street.Buildings = _fakers.Building.GenerateList(1); + street.Buildings[0].Windows = _fakers.Window.GenerateList(3); + street.Buildings[0].PrimaryDoor = _fakers.Door.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -118,10 +118,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(street.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldHaveCount(1); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("windowTotalCount").With(value => value.Should().Be(3)); + responseDocument.Data.SingleValue.Attributes.Should().HaveCount(1); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("windowTotalCount").WhoseValue.Should().Be(3); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); } @@ -129,12 +129,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resource_with_includes() { // Arrange - State state = _fakers.State.Generate(); - state.Cities = _fakers.City.Generate(1); - state.Cities[0].Streets = _fakers.Street.Generate(1); - state.Cities[0].Streets[0].Buildings = _fakers.Building.Generate(1); - state.Cities[0].Streets[0].Buildings[0].PrimaryDoor = _fakers.Door.Generate(); - state.Cities[0].Streets[0].Buildings[0].Windows = _fakers.Window.Generate(3); + State state = _fakers.State.GenerateOne(); + state.Cities = _fakers.City.GenerateList(1); + state.Cities[0].Streets = _fakers.Street.GenerateList(1); + state.Cities[0].Streets[0].Buildings = _fakers.Building.GenerateList(1); + state.Cities[0].Streets[0].Buildings[0].PrimaryDoor = _fakers.Door.GenerateOne(); + state.Cities[0].Streets[0].Buildings[0].Windows = _fakers.Window.GenerateList(3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -150,34 +150,34 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(state.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("name").With(value => value.Should().Be(state.Name)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(state.Name); - responseDocument.Included.ShouldHaveCount(2); + responseDocument.Included.Should().HaveCount(2); responseDocument.Included[0].Type.Should().Be("cities"); responseDocument.Included[0].Id.Should().Be(state.Cities[0].StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("name").With(value => value.Should().Be(state.Cities[0].Name)); + responseDocument.Included[0].Attributes.Should().ContainKey("name").WhoseValue.Should().Be(state.Cities[0].Name); responseDocument.Included[1].Type.Should().Be("streets"); responseDocument.Included[1].Id.Should().Be(state.Cities[0].Streets[0].StringId); - responseDocument.Included[1].Attributes.ShouldContainKey("buildingCount").With(value => value.Should().Be(1)); - responseDocument.Included[1].Attributes.ShouldContainKey("doorTotalCount").With(value => value.Should().Be(1)); - responseDocument.Included[1].Attributes.ShouldContainKey("windowTotalCount").With(value => value.Should().Be(3)); + responseDocument.Included[1].Attributes.Should().ContainKey("buildingCount").WhoseValue.Should().Be(1); + responseDocument.Included[1].Attributes.Should().ContainKey("doorTotalCount").WhoseValue.Should().Be(1); + responseDocument.Included[1].Attributes.Should().ContainKey("windowTotalCount").WhoseValue.Should().Be(3); } [Fact] public async Task Can_get_secondary_resources_with_include_and_fieldsets() { // Arrange - State state = _fakers.State.Generate(); - state.Cities = _fakers.City.Generate(1); - state.Cities[0].Streets = _fakers.Street.Generate(1); - state.Cities[0].Streets[0].Buildings = _fakers.Building.Generate(1); - state.Cities[0].Streets[0].Buildings[0].PrimaryDoor = _fakers.Door.Generate(); - state.Cities[0].Streets[0].Buildings[0].SecondaryDoor = _fakers.Door.Generate(); - state.Cities[0].Streets[0].Buildings[0].Windows = _fakers.Window.Generate(1); + State state = _fakers.State.GenerateOne(); + state.Cities = _fakers.City.GenerateList(1); + state.Cities[0].Streets = _fakers.Street.GenerateList(1); + state.Cities[0].Streets[0].Buildings = _fakers.Building.GenerateList(1); + state.Cities[0].Streets[0].Buildings[0].PrimaryDoor = _fakers.Door.GenerateOne(); + state.Cities[0].Streets[0].Buildings[0].SecondaryDoor = _fakers.Door.GenerateOne(); + state.Cities[0].Streets[0].Buildings[0].Windows = _fakers.Window.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -193,18 +193,18 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(state.Cities[0].StringId); - responseDocument.Data.ManyValue[0].Attributes.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("name").With(value => value.Should().Be(state.Cities[0].Name)); + responseDocument.Data.ManyValue[0].Attributes.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("name").WhoseValue.Should().Be(state.Cities[0].Name); responseDocument.Data.ManyValue[0].Relationships.Should().BeNull(); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("streets"); responseDocument.Included[0].Id.Should().Be(state.Cities[0].Streets[0].StringId); - responseDocument.Included[0].Attributes.ShouldHaveCount(2); - responseDocument.Included[0].Attributes.ShouldContainKey("doorTotalCount").With(value => value.Should().Be(2)); - responseDocument.Included[0].Attributes.ShouldContainKey("windowTotalCount").With(value => value.Should().Be(1)); + responseDocument.Included[0].Attributes.Should().HaveCount(2); + responseDocument.Included[0].Attributes.Should().ContainKey("doorTotalCount").WhoseValue.Should().Be(2); + responseDocument.Included[0].Attributes.Should().ContainKey("windowTotalCount").WhoseValue.Should().Be(1); responseDocument.Included[0].Relationships.Should().BeNull(); } @@ -212,7 +212,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_resource() { // Arrange - Building newBuilding = _fakers.Building.Generate(); + Building newBuilding = _fakers.Building.GenerateOne(); var requestBody = new { @@ -234,13 +234,13 @@ public async Task Can_create_resource() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("number").With(value => value.Should().Be(newBuilding.Number)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("windowCount").With(value => value.Should().Be(0)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("primaryDoorColor").With(value => value.Should().Be("(unspecified)")); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("secondaryDoorColor").With(value => value.Should().BeNull()); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("number").WhoseValue.Should().Be(newBuilding.Number); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("windowCount").WhoseValue.Should().Be(0); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("primaryDoorColor").WhoseValue.Should().Be("(unspecified)"); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("secondaryDoorColor").WhoseValue.Should().BeNull(); - int newBuildingId = int.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + int newBuildingId = int.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -256,9 +256,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // @formatter:wrap_after_property_in_chained_method_calls restore // @formatter:wrap_chained_method_calls restore - buildingInDatabase.ShouldNotBeNull(); + buildingInDatabase.Should().NotBeNull(); buildingInDatabase.Number.Should().Be(newBuilding.Number); - buildingInDatabase.PrimaryDoor.ShouldNotBeNull(); + buildingInDatabase.PrimaryDoor.Should().NotBeNull(); buildingInDatabase.PrimaryDoor.Color.Should().Be("(unspecified)"); buildingInDatabase.SecondaryDoor.Should().BeNull(); buildingInDatabase.Windows.Should().BeEmpty(); @@ -269,13 +269,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource() { // Arrange - Building existingBuilding = _fakers.Building.Generate(); - existingBuilding.PrimaryDoor = _fakers.Door.Generate(); - existingBuilding.SecondaryDoor = _fakers.Door.Generate(); - existingBuilding.Windows = _fakers.Window.Generate(2); + Building existingBuilding = _fakers.Building.GenerateOne(); + existingBuilding.PrimaryDoor = _fakers.Door.GenerateOne(); + existingBuilding.SecondaryDoor = _fakers.Door.GenerateOne(); + existingBuilding.Windows = _fakers.Window.GenerateList(2); - string newBuildingNumber = _fakers.Building.Generate().Number; - string newPrimaryDoorColor = _fakers.Door.Generate().Color; + string newBuildingNumber = _fakers.Building.GenerateOne().Number; + string newPrimaryDoorColor = _fakers.Door.GenerateOne().Color; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -321,12 +321,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // @formatter:wrap_after_property_in_chained_method_calls restore // @formatter:wrap_chained_method_calls restore - buildingInDatabase.ShouldNotBeNull(); + buildingInDatabase.Should().NotBeNull(); buildingInDatabase.Number.Should().Be(newBuildingNumber); - buildingInDatabase.PrimaryDoor.ShouldNotBeNull(); + buildingInDatabase.PrimaryDoor.Should().NotBeNull(); buildingInDatabase.PrimaryDoor.Color.Should().Be(newPrimaryDoorColor); - buildingInDatabase.SecondaryDoor.ShouldNotBeNull(); - buildingInDatabase.Windows.ShouldHaveCount(2); + buildingInDatabase.SecondaryDoor.Should().NotBeNull(); + buildingInDatabase.Windows.Should().HaveCount(2); }); } @@ -334,8 +334,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_when_primaryDoorColor_is_set_to_null() { // Arrange - Building existingBuilding = _fakers.Building.Generate(); - existingBuilding.PrimaryDoor = _fakers.Door.Generate(); + Building existingBuilding = _fakers.Building.GenerateOne(); + existingBuilding.PrimaryDoor = _fakers.Door.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -364,13 +364,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Input validation failed."); error.Detail.Should().Be("The PrimaryDoorColor field is required."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/attributes/primaryDoorColor"); } @@ -378,8 +378,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource() { // Arrange - Building existingBuilding = _fakers.Building.Generate(); - existingBuilding.PrimaryDoor = _fakers.Door.Generate(); + Building existingBuilding = _fakers.Building.GenerateOne(); + existingBuilding.PrimaryDoor = _fakers.Door.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/AlternateExceptionHandler.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/AlternateExceptionHandler.cs index 6e406d9e0c..703cec35cc 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/AlternateExceptionHandler.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/AlternateExceptionHandler.cs @@ -5,7 +5,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ExceptionHandling; -public sealed class AlternateExceptionHandler(ILoggerFactory loggerFactory, IJsonApiOptions options) : ExceptionHandler(loggerFactory, options) +public sealed class AlternateExceptionHandler(ILoggerFactory loggerFactory, IJsonApiOptions options) + : ExceptionHandler(loggerFactory, options) { protected override LogLevel GetLogLevel(Exception exception) { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/ConsumerArticleIsNoLongerAvailableException.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/ConsumerArticleIsNoLongerAvailableException.cs index a1f7f15fcf..18341374f6 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/ConsumerArticleIsNoLongerAvailableException.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/ConsumerArticleIsNoLongerAvailableException.cs @@ -4,8 +4,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ExceptionHandling; -internal sealed class ConsumerArticleIsNoLongerAvailableException(string articleCode, string supportEmailAddress) : JsonApiException( - new ErrorObject(HttpStatusCode.Gone) +internal sealed class ConsumerArticleIsNoLongerAvailableException(string articleCode, string supportEmailAddress) + : JsonApiException(new ErrorObject(HttpStatusCode.Gone) { Title = "The requested article is no longer available.", Detail = $"Article with code '{articleCode}' is no longer available." diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/ConsumerArticleService.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/ConsumerArticleService.cs index fe110f7714..9c2a9fde48 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/ConsumerArticleService.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/ConsumerArticleService.cs @@ -13,8 +13,9 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ExceptionHandling; public sealed class ConsumerArticleService( IResourceRepositoryAccessor repositoryAccessor, IQueryLayerComposer queryLayerComposer, IPaginationContext paginationContext, IJsonApiOptions options, ILoggerFactory loggerFactory, IJsonApiRequest request, IResourceChangeTracker resourceChangeTracker, - IResourceDefinitionAccessor resourceDefinitionAccessor) : JsonApiResourceService(repositoryAccessor, queryLayerComposer, - paginationContext, options, loggerFactory, request, resourceChangeTracker, resourceDefinitionAccessor) + IResourceDefinitionAccessor resourceDefinitionAccessor) + : JsonApiResourceService(repositoryAccessor, queryLayerComposer, paginationContext, options, loggerFactory, request, + resourceChangeTracker, resourceDefinitionAccessor) { private const string SupportEmailAddress = "company@email.com"; internal const string UnavailableArticlePrefix = "X"; diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/ErrorDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/ErrorDbContext.cs index fb90f661fa..c2600dc3d6 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/ErrorDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/ErrorDbContext.cs @@ -5,7 +5,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ExceptionHandling; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class ErrorDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class ErrorDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet ConsumerArticles => Set(); public DbSet ThrowingArticles => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/ExceptionHandlerTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/ExceptionHandlerTests.cs index 06ad682591..35a5364938 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/ExceptionHandlerTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ExceptionHandling/ExceptionHandlerTests.cs @@ -22,19 +22,18 @@ public ExceptionHandlerTests(IntegrationTestContext(); testContext.UseController(); - var loggerFactory = new FakeLoggerFactory(LogLevel.Warning); - testContext.ConfigureLogging(options => { - options.ClearProviders(); - options.AddProvider(loggerFactory); + var loggerProvider = new CapturingLoggerProvider(LogLevel.Warning); + options.AddProvider(loggerProvider); + + options.Services.AddSingleton(loggerProvider); }); testContext.ConfigureServices(services => { services.AddResourceService(); - services.AddSingleton(loggerFactory); services.AddScoped(); }); } @@ -43,8 +42,8 @@ public ExceptionHandlerTests(IntegrationTestContext(); - loggerFactory.Logger.Clear(); + var loggerProvider = _testContext.Factory.Services.GetRequiredService(); + loggerProvider.Clear(); var consumerArticle = new ConsumerArticle { @@ -65,14 +64,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Gone); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Gone); error.Title.Should().Be("The requested article is no longer available."); error.Detail.Should().Be("Article with code 'X123' is no longer available."); - error.Meta.ShouldContainKey("support").With(value => + error.Meta.Should().ContainKey("support").WhoseValue.With(value => { JsonElement element = value.Should().BeOfType().Subject; element.GetString().Should().Be("Please contact us for info about similar articles at company@email.com."); @@ -80,8 +79,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Meta.Should().BeNull(); - IReadOnlyList logMessages = loggerFactory.Logger.GetMessages(); - logMessages.ShouldHaveCount(1); + IReadOnlyList logMessages = loggerProvider.GetMessages(); + logMessages.Should().HaveCount(1); logMessages[0].LogLevel.Should().Be(LogLevel.Warning); logMessages[0].Text.Should().Contain("Article with code 'X123' is no longer available."); @@ -91,8 +90,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Logs_and_produces_error_response_on_deserialization_failure() { // Arrange - var loggerFactory = _testContext.Factory.Services.GetRequiredService(); - loggerFactory.Logger.Clear(); + var loggerProvider = _testContext.Factory.Services.GetRequiredService(); + loggerProvider.Clear(); const string requestBody = """{ "data": { "type": "" } }"""; @@ -104,28 +103,16 @@ public async Task Logs_and_produces_error_response_on_deserialization_failure() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be("Resource type '' does not exist."); + error.Meta.Should().ContainRequestBody(requestBody); + error.Meta.Should().HaveStackTrace(); - error.Meta.ShouldContainKey("requestBody").With(value => - { - JsonElement element = value.Should().BeOfType().Subject; - element.GetString().Should().Be(requestBody); - }); - - error.Meta.ShouldContainKey("stackTrace").With(value => - { - JsonElement element = value.Should().BeOfType().Subject; - IEnumerable stackTraceLines = element.EnumerateArray().Select(token => token.GetString()); - - stackTraceLines.ShouldNotBeEmpty(); - }); - - IReadOnlyList logMessages = loggerFactory.Logger.GetMessages(); + IReadOnlyList logMessages = loggerProvider.GetMessages(); logMessages.Should().BeEmpty(); } @@ -133,8 +120,8 @@ public async Task Logs_and_produces_error_response_on_deserialization_failure() public async Task Logs_and_produces_error_response_on_serialization_failure() { // Arrange - var loggerFactory = _testContext.Factory.Services.GetRequiredService(); - loggerFactory.Logger.Clear(); + var loggerProvider = _testContext.Factory.Services.GetRequiredService(); + loggerProvider.Clear(); var throwingArticle = new ThrowingArticle(); @@ -152,25 +139,18 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.InternalServerError); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.InternalServerError); error.Title.Should().Be("An unhandled error occurred while processing this request."); error.Detail.Should().Be("Exception has been thrown by the target of an invocation."); - - error.Meta.ShouldContainKey("stackTrace").With(value => - { - JsonElement element = value.Should().BeOfType().Subject; - IEnumerable stackTraceLines = element.EnumerateArray().Select(token => token.GetString()); - - stackTraceLines.Should().ContainMatch("*ThrowingArticle*"); - }); + error.Meta.Should().HaveInStackTrace("*ThrowingArticle*"); responseDocument.Meta.Should().BeNull(); - IReadOnlyList logMessages = loggerFactory.Logger.GetMessages(); - logMessages.ShouldHaveCount(1); + IReadOnlyList logMessages = loggerProvider.GetMessages(); + logMessages.Should().HaveCount(1); logMessages[0].LogLevel.Should().Be(LogLevel.Error); logMessages[0].Text.Should().Contain("Exception has been thrown by the target of an invocation."); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/HitCountingResourceDefinition.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/HitCountingResourceDefinition.cs index 3a51f0961f..8cd361ef99 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/HitCountingResourceDefinition.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/HitCountingResourceDefinition.cs @@ -1,5 +1,4 @@ using System.Collections.Immutable; -using JsonApiDotNetCore; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Middleware; using JsonApiDotNetCore.Queries.Expressions; @@ -22,7 +21,7 @@ public abstract class HitCountingResourceDefinition : JsonApiRes protected HitCountingResourceDefinition(IResourceGraph resourceGraph, ResourceDefinitionHitCounter hitCounter) : base(resourceGraph) { - ArgumentGuard.NotNull(hitCounter); + ArgumentNullException.ThrowIfNull(hitCounter); _hitCounter = hitCounter; } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/HostingInIIS/HostingDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/HostingInIIS/HostingDbContext.cs index a27f87c770..2df6d9e390 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/HostingInIIS/HostingDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/HostingInIIS/HostingDbContext.cs @@ -5,7 +5,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.HostingInIIS; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class HostingDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class HostingDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet ArtGalleries => Set(); public DbSet Paintings => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/HostingInIIS/HostingTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/HostingInIIS/HostingTests.cs index 872cd44c3a..d3ab6edd78 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/HostingInIIS/HostingTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/HostingInIIS/HostingTests.cs @@ -25,8 +25,8 @@ public HostingTests(IntegrationTestContext, Hos public async Task Get_primary_resources_with_include_returns_links() { // Arrange - ArtGallery gallery = _fakers.ArtGallery.Generate(); - gallery.Paintings = _fakers.Painting.Generate(1).ToHashSet(); + ArtGallery gallery = _fakers.ArtGallery.GenerateOne(); + gallery.Paintings = _fakers.Painting.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -43,7 +43,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().Be(responseDocument.Links.Self); @@ -51,19 +51,19 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Prev.Should().BeNull(); responseDocument.Links.Next.Should().BeNull(); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].With(resource => { string galleryLink = $"{HostPrefix}/iis-application-virtual-directory/public-api/artGalleries/{gallery.StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(galleryLink); - resource.Relationships.ShouldContainKey("paintings").With(value => + resource.Relationships.Should().ContainKey("paintings").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{galleryLink}/relationships/paintings"); value.Links.Related.Should().Be($"{galleryLink}/paintings"); }); @@ -71,17 +71,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => string paintingLink = $"{HostPrefix}/iis-application-virtual-directory/custom/path/to/paintings-of-the-world/{gallery.Paintings.ElementAt(0).StringId}"; - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].With(resource => { - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(paintingLink); - resource.Relationships.ShouldContainKey("exposedAt").With(value => + resource.Relationships.Should().ContainKey("exposedAt").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{paintingLink}/relationships/exposedAt"); value.Links.Related.Should().Be($"{paintingLink}/exposedAt"); }); @@ -92,8 +92,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_primary_resources_with_include_on_custom_route_returns_links() { // Arrange - Painting painting = _fakers.Painting.Generate(); - painting.ExposedAt = _fakers.ArtGallery.Generate(); + Painting painting = _fakers.Painting.GenerateOne(); + painting.ExposedAt = _fakers.ArtGallery.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -110,7 +110,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().Be(responseDocument.Links.Self); @@ -118,37 +118,37 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Prev.Should().BeNull(); responseDocument.Links.Next.Should().BeNull(); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].With(resource => { string paintingLink = $"{HostPrefix}/iis-application-virtual-directory/custom/path/to/paintings-of-the-world/{painting.StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(paintingLink); - resource.Relationships.ShouldContainKey("exposedAt").With(value => + resource.Relationships.Should().ContainKey("exposedAt").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{paintingLink}/relationships/exposedAt"); value.Links.Related.Should().Be($"{paintingLink}/exposedAt"); }); }); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].With(resource => { string galleryLink = $"{HostPrefix}/iis-application-virtual-directory/public-api/artGalleries/{painting.ExposedAt.StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(galleryLink); - resource.Relationships.ShouldContainKey("paintings").With(value => + resource.Relationships.Should().ContainKey("paintings").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{galleryLink}/relationships/paintings"); value.Links.Related.Should().Be($"{galleryLink}/paintings"); }); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/IdObfuscationTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/IdObfuscationTests.cs index 031ed80fce..e5383f3f7d 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/IdObfuscationTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/IdObfuscationTests.cs @@ -24,7 +24,7 @@ public IdObfuscationTests(IntegrationTestContext accounts = _fakers.BankAccount.Generate(2); + List accounts = _fakers.BankAccount.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -41,7 +41,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(accounts[1].StringId); } @@ -58,13 +58,13 @@ public async Task Cannot_filter_equality_for_invalid_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified filter is invalid."); error.Detail.Should().Be($"The value 'not-a-hex-value' is not a valid hexadecimal value. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("filter"); } @@ -72,7 +72,7 @@ public async Task Cannot_filter_equality_for_invalid_ID() public async Task Can_filter_any_in_primary_resources() { // Arrange - List accounts = _fakers.BankAccount.Generate(2); + List accounts = _fakers.BankAccount.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -90,7 +90,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(accounts[1].StringId); } @@ -106,7 +106,7 @@ public async Task Cannot_get_primary_resource_for_invalid_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); @@ -118,8 +118,8 @@ public async Task Cannot_get_primary_resource_for_invalid_ID() public async Task Can_get_primary_resource_by_ID() { // Arrange - DebitCard card = _fakers.DebitCard.Generate(); - card.Account = _fakers.BankAccount.Generate(); + DebitCard card = _fakers.DebitCard.GenerateOne(); + card.Account = _fakers.BankAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -135,7 +135,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(card.StringId); } @@ -143,8 +143,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_secondary_resources() { // Arrange - BankAccount account = _fakers.BankAccount.Generate(); - account.Cards = _fakers.DebitCard.Generate(2); + BankAccount account = _fakers.BankAccount.GenerateOne(); + account.Cards = _fakers.DebitCard.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -160,7 +160,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue[0].Id.Should().Be(account.Cards[0].StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(account.Cards[1].StringId); } @@ -169,8 +169,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_include_resource_with_sparse_fieldset() { // Arrange - BankAccount account = _fakers.BankAccount.Generate(); - account.Cards = _fakers.DebitCard.Generate(1); + BankAccount account = _fakers.BankAccount.GenerateOne(); + account.Cards = _fakers.DebitCard.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -186,12 +186,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(account.StringId); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Id.Should().Be(account.Cards[0].StringId); - responseDocument.Included[0].Attributes.ShouldHaveCount(1); + responseDocument.Included[0].Attributes.Should().HaveCount(1); responseDocument.Included[0].Relationships.Should().BeNull(); } @@ -199,8 +199,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_relationship() { // Arrange - BankAccount account = _fakers.BankAccount.Generate(); - account.Cards = _fakers.DebitCard.Generate(1); + BankAccount account = _fakers.BankAccount.GenerateOne(); + account.Cards = _fakers.DebitCard.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -216,7 +216,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(account.Cards[0].StringId); } @@ -224,8 +224,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_resource_with_relationship() { // Arrange - BankAccount existingAccount = _fakers.BankAccount.Generate(); - DebitCard newCard = _fakers.DebitCard.Generate(); + BankAccount existingAccount = _fakers.BankAccount.GenerateOne(); + DebitCard newCard = _fakers.DebitCard.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -265,9 +265,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("ownerName").With(value => value.Should().Be(newCard.OwnerName)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("pinCode").With(value => value.Should().Be(newCard.PinCode)); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("ownerName").WhoseValue.Should().Be(newCard.OwnerName); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("pinCode").WhoseValue.Should().Be(newCard.PinCode); var codec = new HexadecimalCodec(); int newCardId = codec.Decode(responseDocument.Data.SingleValue.Id); @@ -279,7 +279,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => cardInDatabase.OwnerName.Should().Be(newCard.OwnerName); cardInDatabase.PinCode.Should().Be(newCard.PinCode); - cardInDatabase.Account.ShouldNotBeNull(); + cardInDatabase.Account.Should().NotBeNull(); cardInDatabase.Account.Id.Should().Be(existingAccount.Id); cardInDatabase.Account.StringId.Should().Be(existingAccount.StringId); }); @@ -289,13 +289,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_relationship() { // Arrange - BankAccount existingAccount = _fakers.BankAccount.Generate(); - existingAccount.Cards = _fakers.DebitCard.Generate(1); + BankAccount existingAccount = _fakers.BankAccount.GenerateOne(); + existingAccount.Cards = _fakers.DebitCard.GenerateList(1); - DebitCard existingCard = _fakers.DebitCard.Generate(); - existingCard.Account = _fakers.BankAccount.Generate(); + DebitCard existingCard = _fakers.DebitCard.GenerateOne(); + existingCard.Account = _fakers.BankAccount.GenerateOne(); - string newIban = _fakers.BankAccount.Generate().Iban; + string newIban = _fakers.BankAccount.GenerateOne().Iban; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -346,7 +346,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => accountInDatabase.Iban.Should().Be(newIban); - accountInDatabase.Cards.ShouldHaveCount(1); + accountInDatabase.Cards.Should().HaveCount(1); accountInDatabase.Cards[0].Id.Should().Be(existingCard.Id); accountInDatabase.Cards[0].StringId.Should().Be(existingCard.StringId); }); @@ -356,11 +356,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_to_ToMany_relationship() { // Arrange - BankAccount existingAccount = _fakers.BankAccount.Generate(); - existingAccount.Cards = _fakers.DebitCard.Generate(1); + BankAccount existingAccount = _fakers.BankAccount.GenerateOne(); + existingAccount.Cards = _fakers.DebitCard.GenerateList(1); - DebitCard existingDebitCard = _fakers.DebitCard.Generate(); - existingDebitCard.Account = _fakers.BankAccount.Generate(); + DebitCard existingDebitCard = _fakers.DebitCard.GenerateOne(); + existingDebitCard.Account = _fakers.BankAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -394,7 +394,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { BankAccount accountInDatabase = await dbContext.BankAccounts.Include(account => account.Cards).FirstWithIdAsync(existingAccount.Id); - accountInDatabase.Cards.ShouldHaveCount(2); + accountInDatabase.Cards.Should().HaveCount(2); }); } @@ -402,8 +402,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_ToMany_relationship() { // Arrange - BankAccount existingAccount = _fakers.BankAccount.Generate(); - existingAccount.Cards = _fakers.DebitCard.Generate(2); + BankAccount existingAccount = _fakers.BankAccount.GenerateOne(); + existingAccount.Cards = _fakers.DebitCard.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -437,7 +437,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { BankAccount accountInDatabase = await dbContext.BankAccounts.Include(account => account.Cards).FirstWithIdAsync(existingAccount.Id); - accountInDatabase.Cards.ShouldHaveCount(1); + accountInDatabase.Cards.Should().HaveCount(1); }); } @@ -445,8 +445,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource() { // Arrange - BankAccount existingAccount = _fakers.BankAccount.Generate(); - existingAccount.Cards = _fakers.DebitCard.Generate(1); + BankAccount existingAccount = _fakers.BankAccount.GenerateOne(); + existingAccount.Cards = _fakers.DebitCard.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -487,7 +487,7 @@ public async Task Cannot_delete_unknown_resource() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/ObfuscatedIdentifiable.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/ObfuscatedIdentifiable.cs index 0aa2203d8a..af6a8a1416 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/ObfuscatedIdentifiable.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/ObfuscatedIdentifiable.cs @@ -8,11 +8,11 @@ public abstract class ObfuscatedIdentifiable : Identifiable protected override string? GetStringId(int value) { - return value == default ? null : Codec.Encode(value); + return value == 0 ? null : Codec.Encode(value); } protected override int GetTypedId(string? value) { - return value == null ? default : Codec.Decode(value); + return value == null ? 0 : Codec.Decode(value); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/ObfuscatedIdentifiableController.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/ObfuscatedIdentifiableController.cs index 1c93a9c08c..ffe73f7b9a 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/ObfuscatedIdentifiableController.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/ObfuscatedIdentifiableController.cs @@ -6,6 +6,8 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; +#pragma warning disable format + namespace JsonApiDotNetCoreTests.IntegrationTests.IdObfuscation; public abstract class ObfuscatedIdentifiableController( @@ -16,12 +18,14 @@ public abstract class ObfuscatedIdentifiableController( private readonly HexadecimalCodec _codec = new(); [HttpGet] + [HttpHead] public override Task GetAsync(CancellationToken cancellationToken) { return base.GetAsync(cancellationToken); } [HttpGet("{id}")] + [HttpHead("{id}")] public Task GetAsync([Required] string id, CancellationToken cancellationToken) { int idValue = _codec.Decode(id); @@ -29,14 +33,18 @@ public Task GetAsync([Required] string id, CancellationToken canc } [HttpGet("{id}/{relationshipName}")] - public Task GetSecondaryAsync([Required] string id, [Required] string relationshipName, CancellationToken cancellationToken) + [HttpHead("{id}/{relationshipName}")] + public Task GetSecondaryAsync([Required] string id, [Required] [PreserveEmptyString] string relationshipName, + CancellationToken cancellationToken) { int idValue = _codec.Decode(id); return base.GetSecondaryAsync(idValue, relationshipName, cancellationToken); } [HttpGet("{id}/relationships/{relationshipName}")] - public Task GetRelationshipAsync([Required] string id, [Required] string relationshipName, CancellationToken cancellationToken) + [HttpHead("{id}/relationships/{relationshipName}")] + public Task GetRelationshipAsync([Required] string id, [Required] [PreserveEmptyString] string relationshipName, + CancellationToken cancellationToken) { int idValue = _codec.Decode(id); return base.GetRelationshipAsync(idValue, relationshipName, cancellationToken); @@ -49,7 +57,7 @@ public override Task PostAsync([FromBody] [Required] TResource re } [HttpPost("{id}/relationships/{relationshipName}")] - public Task PostRelationshipAsync([Required] string id, [Required] string relationshipName, + public Task PostRelationshipAsync([Required] string id, [Required] [PreserveEmptyString] string relationshipName, [FromBody] [Required] ISet rightResourceIds, CancellationToken cancellationToken) { int idValue = _codec.Decode(id); @@ -65,8 +73,8 @@ public Task PatchAsync([Required] string id, [FromBody] [Required [HttpPatch("{id}/relationships/{relationshipName}")] // Parameter `[Required] object? rightValue` makes Swashbuckle generate the OpenAPI request body as required. We don't actually validate ModelState, so it doesn't hurt. - public Task PatchRelationshipAsync([Required] string id, [Required] string relationshipName, [FromBody] [Required] object? rightValue, - CancellationToken cancellationToken) + public Task PatchRelationshipAsync([Required] string id, [Required] [PreserveEmptyString] string relationshipName, + [FromBody] [Required] object? rightValue, CancellationToken cancellationToken) { int idValue = _codec.Decode(id); return base.PatchRelationshipAsync(idValue, relationshipName, rightValue, cancellationToken); @@ -80,7 +88,7 @@ public Task DeleteAsync([Required] string id, CancellationToken c } [HttpDelete("{id}/relationships/{relationshipName}")] - public Task DeleteRelationshipAsync([Required] string id, [Required] string relationshipName, + public Task DeleteRelationshipAsync([Required] string id, [Required] [PreserveEmptyString] string relationshipName, [FromBody] [Required] ISet rightResourceIds, CancellationToken cancellationToken) { int idValue = _codec.Decode(id); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/ObfuscationDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/ObfuscationDbContext.cs index 820a6cf554..94188a7d60 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/ObfuscationDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/ObfuscationDbContext.cs @@ -5,7 +5,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.IdObfuscation; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class ObfuscationDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class ObfuscationDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet BankAccounts => Set(); public DbSet DebitCards => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/ModelStateDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/ModelStateDbContext.cs index 3d41c39035..9a480988cc 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/ModelStateDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/ModelStateDbContext.cs @@ -7,7 +7,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.InputValidation.ModelState; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class ModelStateDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class ModelStateDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet Volumes => Set(); public DbSet Directories => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/ModelStateValidationTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/ModelStateValidationTests.cs index 21fe575a2b..7cedc98f5e 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/ModelStateValidationTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/ModelStateValidationTests.cs @@ -3,9 +3,6 @@ using JsonApiDotNetCore.Serialization.Objects; using TestBuildingBlocks; using Xunit; -#if NET6_0 -using Microsoft.Extensions.DependencyInjection; -#endif namespace JsonApiDotNetCoreTests.IntegrationTests.InputValidation.ModelState; @@ -20,12 +17,6 @@ public ModelStateValidationTests(IntegrationTestContext(); testContext.UseController(); - -#if NET6_0 - testContext.ConfigureServices(services => - // Polyfill for missing DateOnly/TimeOnly support in .NET 6 ModelState validation. - services.AddDateOnlyTimeOnlyStringConverters()); -#endif } [Fact] @@ -52,13 +43,13 @@ public async Task Cannot_create_resource_with_omitted_required_attribute() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Input validation failed."); error.Detail.Should().Be("The Name field is required."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/attributes/directoryName"); } @@ -87,13 +78,13 @@ public async Task Cannot_create_resource_with_null_for_required_attribute_value( // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Input validation failed."); error.Detail.Should().Be("The Name field is required."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/attributes/directoryName"); } @@ -122,13 +113,13 @@ public async Task Cannot_create_resource_with_invalid_attribute_value() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Input validation failed."); error.Detail.Should().Be(@"The field Name must match the regular expression '^[\w\s]+$'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/attributes/directoryName"); } @@ -136,7 +127,7 @@ public async Task Cannot_create_resource_with_invalid_attribute_value() public async Task Cannot_create_resource_with_invalid_DateOnly_TimeOnly_attribute_value() { // Arrange - SystemFile newFile = _fakers.SystemFile.Generate(); + SystemFile newFile = _fakers.SystemFile.GenerateOne(); var requestBody = new { @@ -162,20 +153,20 @@ public async Task Cannot_create_resource_with_invalid_DateOnly_TimeOnly_attribut // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(2); + responseDocument.Errors.Should().HaveCount(2); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error1.Title.Should().Be("Input validation failed."); error1.Detail.Should().StartWith("The field CreatedAt must be between "); - error1.Source.ShouldNotBeNull(); + error1.Source.Should().NotBeNull(); error1.Source.Pointer.Should().Be("/data/attributes/createdAt"); ErrorObject error2 = responseDocument.Errors[1]; error2.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error2.Title.Should().Be("Input validation failed."); error2.Detail.Should().StartWith("The field CreatedOn must be between "); - error2.Source.ShouldNotBeNull(); + error2.Source.Should().NotBeNull(); error2.Source.Pointer.Should().Be("/data/attributes/createdOn"); } @@ -183,7 +174,7 @@ public async Task Cannot_create_resource_with_invalid_DateOnly_TimeOnly_attribut public async Task Can_create_resource_with_valid_attribute_value() { // Arrange - SystemDirectory newDirectory = _fakers.SystemDirectory.Generate(); + SystemDirectory newDirectory = _fakers.SystemDirectory.GenerateOne(); var requestBody = new { @@ -206,9 +197,9 @@ public async Task Can_create_resource_with_valid_attribute_value() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("directoryName").With(value => value.Should().Be(newDirectory.Name)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("isCaseSensitive").With(value => value.Should().Be(newDirectory.IsCaseSensitive)); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("directoryName").WhoseValue.Should().Be(newDirectory.Name); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("isCaseSensitive").WhoseValue.Should().Be(newDirectory.IsCaseSensitive); } [Fact] @@ -234,20 +225,20 @@ public async Task Cannot_create_resource_with_multiple_violations() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(2); + responseDocument.Errors.Should().HaveCount(2); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error1.Title.Should().Be("Input validation failed."); error1.Detail.Should().Be("The Name field is required."); - error1.Source.ShouldNotBeNull(); + error1.Source.Should().NotBeNull(); error1.Source.Pointer.Should().Be("/data/attributes/directoryName"); ErrorObject error2 = responseDocument.Errors[1]; error2.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error2.Title.Should().Be("Input validation failed."); error2.Detail.Should().Be("The IsCaseSensitive field is required."); - error2.Source.ShouldNotBeNull(); + error2.Source.Should().NotBeNull(); error2.Source.Pointer.Should().Be("/data/attributes/isCaseSensitive"); } @@ -274,7 +265,7 @@ public async Task Does_not_exceed_MaxModelValidationErrors() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(3); + responseDocument.Errors.Should().HaveCount(3); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); @@ -286,14 +277,14 @@ public async Task Does_not_exceed_MaxModelValidationErrors() error2.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error2.Title.Should().Be("Input validation failed."); error2.Detail.Should().Be("The FileName field is required."); - error2.Source.ShouldNotBeNull(); + error2.Source.Should().NotBeNull(); error2.Source.Pointer.Should().Be("/data/attributes/fileName"); ErrorObject error3 = responseDocument.Errors[2]; error3.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error3.Title.Should().Be("Input validation failed."); error3.Detail.Should().Be("The Attributes field is required."); - error3.Source.ShouldNotBeNull(); + error3.Source.Should().NotBeNull(); error3.Source.Pointer.Should().Be("/data/attributes/attributes"); } @@ -301,11 +292,11 @@ public async Task Does_not_exceed_MaxModelValidationErrors() public async Task Can_create_resource_with_annotated_relationships() { // Arrange - SystemDirectory existingParentDirectory = _fakers.SystemDirectory.Generate(); - SystemDirectory existingSubdirectory = _fakers.SystemDirectory.Generate(); - SystemFile existingFile = _fakers.SystemFile.Generate(); + SystemDirectory existingParentDirectory = _fakers.SystemDirectory.GenerateOne(); + SystemDirectory existingSubdirectory = _fakers.SystemDirectory.GenerateOne(); + SystemFile existingFile = _fakers.SystemFile.GenerateOne(); - SystemDirectory newDirectory = _fakers.SystemDirectory.Generate(); + SystemDirectory newDirectory = _fakers.SystemDirectory.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -368,17 +359,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("directoryName").With(value => value.Should().Be(newDirectory.Name)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("isCaseSensitive").With(value => value.Should().Be(newDirectory.IsCaseSensitive)); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("directoryName").WhoseValue.Should().Be(newDirectory.Name); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("isCaseSensitive").WhoseValue.Should().Be(newDirectory.IsCaseSensitive); } [Fact] public async Task Can_add_to_annotated_ToMany_relationship() { // Arrange - SystemDirectory existingDirectory = _fakers.SystemDirectory.Generate(); - SystemFile existingFile = _fakers.SystemFile.Generate(); + SystemDirectory existingDirectory = _fakers.SystemDirectory.GenerateOne(); + SystemFile existingFile = _fakers.SystemFile.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -413,9 +404,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_omitted_required_attribute_value() { // Arrange - SystemFile existingFile = _fakers.SystemFile.Generate(); + SystemFile existingFile = _fakers.SystemFile.GenerateOne(); - long? newSizeInBytes = _fakers.SystemFile.Generate().SizeInBytes; + long? newSizeInBytes = _fakers.SystemFile.GenerateOne().SizeInBytes; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -451,7 +442,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_null_for_required_attribute_values() { // Arrange - SystemDirectory existingDirectory = _fakers.SystemDirectory.Generate(); + SystemDirectory existingDirectory = _fakers.SystemDirectory.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -481,20 +472,20 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(2); + responseDocument.Errors.Should().HaveCount(2); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error1.Title.Should().Be("Input validation failed."); error1.Detail.Should().Be("The Name field is required."); - error1.Source.ShouldNotBeNull(); + error1.Source.Should().NotBeNull(); error1.Source.Pointer.Should().Be("/data/attributes/directoryName"); ErrorObject error2 = responseDocument.Errors[1]; error2.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error2.Title.Should().Be("Input validation failed."); error2.Detail.Should().Be("The IsCaseSensitive field is required."); - error2.Source.ShouldNotBeNull(); + error2.Source.Should().NotBeNull(); error2.Source.Pointer.Should().Be("/data/attributes/isCaseSensitive"); } @@ -502,7 +493,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_invalid_attribute_value() { // Arrange - SystemDirectory existingDirectory = _fakers.SystemDirectory.Generate(); + SystemDirectory existingDirectory = _fakers.SystemDirectory.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -531,13 +522,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Input validation failed."); error.Detail.Should().Be(@"The field Name must match the regular expression '^[\w\s]+$'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/attributes/directoryName"); } @@ -576,20 +567,20 @@ public async Task Cannot_update_resource_with_invalid_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(2); + responseDocument.Errors.Should().HaveCount(2); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error1.Title.Should().Be("Input validation failed."); error1.Detail.Should().Be("The field Id must match the regular expression '^[0-9]+$'."); - error1.Source.ShouldNotBeNull(); + error1.Source.Should().NotBeNull(); error1.Source.Pointer.Should().Be("/data/id"); ErrorObject error2 = responseDocument.Errors[1]; error2.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error2.Title.Should().Be("Input validation failed."); error2.Detail.Should().Be("The field Id must match the regular expression '^[0-9]+$'."); - error2.Source.ShouldNotBeNull(); + error2.Source.Should().NotBeNull(); error2.Source.Pointer.Should().Be("/data/relationships/subdirectories/data[0]/id"); } @@ -597,9 +588,9 @@ public async Task Cannot_update_resource_with_invalid_ID() public async Task Can_update_resource_with_valid_attribute_value() { // Arrange - SystemDirectory existingDirectory = _fakers.SystemDirectory.Generate(); + SystemDirectory existingDirectory = _fakers.SystemDirectory.GenerateOne(); - string newDirectoryName = _fakers.SystemDirectory.Generate().Name; + string newDirectoryName = _fakers.SystemDirectory.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -635,16 +626,16 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_annotated_relationships() { // Arrange - SystemDirectory existingDirectory = _fakers.SystemDirectory.Generate(); - existingDirectory.Subdirectories = _fakers.SystemDirectory.Generate(1); - existingDirectory.Files = _fakers.SystemFile.Generate(1); - existingDirectory.Parent = _fakers.SystemDirectory.Generate(); + SystemDirectory existingDirectory = _fakers.SystemDirectory.GenerateOne(); + existingDirectory.Subdirectories = _fakers.SystemDirectory.GenerateList(1); + existingDirectory.Files = _fakers.SystemFile.GenerateList(1); + existingDirectory.Parent = _fakers.SystemDirectory.GenerateOne(); - SystemDirectory existingParent = _fakers.SystemDirectory.Generate(); - SystemDirectory existingSubdirectory = _fakers.SystemDirectory.Generate(); - SystemFile existingFile = _fakers.SystemFile.Generate(); + SystemDirectory existingParent = _fakers.SystemDirectory.GenerateOne(); + SystemDirectory existingSubdirectory = _fakers.SystemDirectory.GenerateOne(); + SystemFile existingFile = _fakers.SystemFile.GenerateOne(); - string newDirectoryName = _fakers.SystemDirectory.Generate().Name; + string newDirectoryName = _fakers.SystemDirectory.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -714,7 +705,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_multiple_self_references() { // Arrange - SystemDirectory existingDirectory = _fakers.SystemDirectory.Generate(); + SystemDirectory existingDirectory = _fakers.SystemDirectory.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -765,7 +756,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_collection_of_self_references() { // Arrange - SystemDirectory existingDirectory = _fakers.SystemDirectory.Generate(); + SystemDirectory existingDirectory = _fakers.SystemDirectory.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -811,10 +802,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_annotated_ToOne_relationship() { // Arrange - SystemDirectory existingDirectory = _fakers.SystemDirectory.Generate(); - existingDirectory.Parent = _fakers.SystemDirectory.Generate(); + SystemDirectory existingDirectory = _fakers.SystemDirectory.GenerateOne(); + existingDirectory.Parent = _fakers.SystemDirectory.GenerateOne(); - SystemDirectory otherExistingDirectory = _fakers.SystemDirectory.Generate(); + SystemDirectory otherExistingDirectory = _fakers.SystemDirectory.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -846,10 +837,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_annotated_ToMany_relationship() { // Arrange - SystemDirectory existingDirectory = _fakers.SystemDirectory.Generate(); - existingDirectory.Files = _fakers.SystemFile.Generate(2); + SystemDirectory existingDirectory = _fakers.SystemDirectory.GenerateOne(); + existingDirectory.Files = _fakers.SystemFile.GenerateList(2); - SystemFile existingFile = _fakers.SystemFile.Generate(); + SystemFile existingFile = _fakers.SystemFile.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -884,8 +875,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_annotated_ToMany_relationship() { // Arrange - SystemDirectory existingDirectory = _fakers.SystemDirectory.Generate(); - existingDirectory.Files = _fakers.SystemFile.Generate(1); + SystemDirectory existingDirectory = _fakers.SystemDirectory.GenerateOne(); + existingDirectory.Files = _fakers.SystemFile.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/NoModelStateValidationTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/NoModelStateValidationTests.cs index ec3d49fe7a..4245ff2fc1 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/NoModelStateValidationTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/ModelState/NoModelStateValidationTests.cs @@ -46,15 +46,15 @@ public async Task Can_create_resource_with_invalid_attribute_value() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("directoryName").With(value => value.Should().Be("!@#$%^&*().-")); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("directoryName").WhoseValue.Should().Be("!@#$%^&*().-"); } [Fact] public async Task Can_update_resource_with_invalid_attribute_value() { // Arrange - SystemDirectory existingDirectory = _fakers.SystemDirectory.Generate(); + SystemDirectory existingDirectory = _fakers.SystemDirectory.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -90,8 +90,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_clear_required_OneToOne_relationship_at_primary_endpoint() { // Arrange - SystemVolume existingVolume = _fakers.SystemVolume.Generate(); - existingVolume.RootDirectory = _fakers.SystemDirectory.Generate(); + SystemVolume existingVolume = _fakers.SystemVolume.GenerateOne(); + existingVolume.RootDirectory = _fakers.SystemDirectory.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -123,7 +123,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/RequestBody/WorkflowDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/RequestBody/WorkflowDbContext.cs index e49e5618a2..e7c264ab11 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/RequestBody/WorkflowDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/RequestBody/WorkflowDbContext.cs @@ -7,7 +7,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.InputValidation.RequestBody; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class WorkflowDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class WorkflowDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet Workflows => Set(); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/RequestBody/WorkflowDefinition.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/RequestBody/WorkflowDefinition.cs index cdcd268558..aaa35af882 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/RequestBody/WorkflowDefinition.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/RequestBody/WorkflowDefinition.cs @@ -9,26 +9,31 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.InputValidation.RequestBody; [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] -public sealed class WorkflowDefinition(IResourceGraph resourceGraph) : JsonApiResourceDefinition(resourceGraph) +public sealed class WorkflowDefinition(IResourceGraph resourceGraph) + : JsonApiResourceDefinition(resourceGraph) { - private static readonly Dictionary> StageTransitionTable = new() + private static readonly Dictionary StageTransitionTable = new() { - [WorkflowStage.Created] = new[] - { + // @formatter:place_simple_list_pattern_on_single_line false + + [WorkflowStage.Created] = + [ WorkflowStage.InProgress - }, - [WorkflowStage.InProgress] = new[] - { + ], + [WorkflowStage.InProgress] = + [ WorkflowStage.OnHold, WorkflowStage.Succeeded, WorkflowStage.Failed, WorkflowStage.Canceled - }, - [WorkflowStage.OnHold] = new[] - { + ], + [WorkflowStage.OnHold] = + [ WorkflowStage.InProgress, WorkflowStage.Canceled - } + ] + + // @formatter:place_simple_list_pattern_on_single_line restore }; private WorkflowStage _previousStage; @@ -93,7 +98,7 @@ private static void AssertCanTransitionToStage(WorkflowStage fromStage, Workflow private static bool CanTransitionToStage(WorkflowStage fromStage, WorkflowStage toStage) { - if (StageTransitionTable.TryGetValue(fromStage, out ICollection? possibleNextStages)) + if (StageTransitionTable.TryGetValue(fromStage, out WorkflowStage[]? possibleNextStages)) { return possibleNextStages.Contains(toStage); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/RequestBody/WorkflowTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/RequestBody/WorkflowTests.cs index 290a168fb1..9b8fd9cbc9 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/RequestBody/WorkflowTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/InputValidation/RequestBody/WorkflowTests.cs @@ -44,7 +44,7 @@ public async Task Can_create_in_valid_stage() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); } [Fact] @@ -71,13 +71,13 @@ public async Task Cannot_create_in_invalid_stage() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Invalid workflow stage."); error.Detail.Should().Be("Initial stage of workflow must be 'Created'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/attributes/stage"); } @@ -117,13 +117,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Invalid workflow stage."); error.Detail.Should().Be("Cannot transition from 'OnHold' to 'Succeeded'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/attributes/stage"); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/AbsoluteLinksWithNamespaceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/AbsoluteLinksWithNamespaceTests.cs index 6806eeed7b..688ef470b8 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/AbsoluteLinksWithNamespaceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/AbsoluteLinksWithNamespaceTests.cs @@ -35,7 +35,7 @@ public AbsoluteLinksWithNamespaceTests(IntegrationTestContext { @@ -51,7 +51,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().BeNull(); @@ -60,14 +60,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Links.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Links.Should().NotBeNull(); responseDocument.Data.SingleValue.Links.Self.Should().Be($"{HostPrefix}{route}"); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("photos").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("photos").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{HostPrefix}{route}/relationships/photos"); value.Links.Related.Should().Be($"{HostPrefix}{route}/photos"); }); @@ -77,8 +77,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_primary_resources_with_include_returns_absolute_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -95,7 +95,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().Be(responseDocument.Links.Self); @@ -104,37 +104,37 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].With(resource => { string albumLink = $"{HostPrefix}{PathPrefix}/photoAlbums/{album.StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(albumLink); - resource.Relationships.ShouldContainKey("photos").With(value => + resource.Relationships.Should().ContainKey("photos").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{albumLink}/relationships/photos"); value.Links.Related.Should().Be($"{albumLink}/photos"); }); }); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].With(resource => { string photoLink = $"{HostPrefix}{PathPrefix}/photos/{album.Photos.ElementAt(0).StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(photoLink); - resource.Relationships.ShouldContainKey("album").With(value => + resource.Relationships.Should().ContainKey("album").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{photoLink}/relationships/album"); value.Links.Related.Should().Be($"{photoLink}/album"); }); @@ -145,8 +145,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resource_returns_absolute_links() { // Arrange - Photo photo = _fakers.Photo.Generate(); - photo.Album = _fakers.PhotoAlbum.Generate(); + Photo photo = _fakers.Photo.GenerateOne(); + photo.Album = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -162,7 +162,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().BeNull(); @@ -173,14 +173,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => string albumLink = $"{HostPrefix}{PathPrefix}/photoAlbums/{photo.Album.StringId}"; - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Links.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Links.Should().NotBeNull(); responseDocument.Data.SingleValue.Links.Self.Should().Be(albumLink); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("photos").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("photos").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{albumLink}/relationships/photos"); value.Links.Related.Should().Be($"{albumLink}/photos"); }); @@ -190,8 +190,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resources_returns_absolute_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -207,7 +207,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().Be(responseDocument.Links.Self); @@ -216,19 +216,19 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].With(resource => { string photoLink = $"{HostPrefix}{PathPrefix}/photos/{album.Photos.ElementAt(0).StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(photoLink); - resource.Relationships.ShouldContainKey("album").With(value => + resource.Relationships.Should().ContainKey("album").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{photoLink}/relationships/album"); value.Links.Related.Should().Be($"{photoLink}/album"); }); @@ -239,8 +239,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_ToOne_relationship_returns_absolute_links() { // Arrange - Photo photo = _fakers.Photo.Generate(); - photo.Album = _fakers.PhotoAlbum.Generate(); + Photo photo = _fakers.Photo.GenerateOne(); + photo.Album = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -256,7 +256,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().Be($"{HostPrefix}{PathPrefix}/photos/{photo.StringId}/album"); responseDocument.Links.First.Should().BeNull(); @@ -265,7 +265,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Links.Should().BeNull(); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); } @@ -274,8 +274,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_ToMany_relationship_returns_absolute_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -291,7 +291,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().Be($"{HostPrefix}{PathPrefix}/photoAlbums/{album.StringId}/photos"); responseDocument.Links.First.Should().Be(responseDocument.Links.Self); @@ -300,7 +300,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Links.Should().BeNull(); responseDocument.Data.ManyValue[0].Relationships.Should().BeNull(); } @@ -309,9 +309,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Create_resource_with_side_effects_and_include_returns_absolute_links() { // Arrange - Photo existingPhoto = _fakers.Photo.Generate(); + Photo existingPhoto = _fakers.Photo.GenerateOne(); - string newAlbumName = _fakers.PhotoAlbum.Generate().Name; + string newAlbumName = _fakers.PhotoAlbum.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -353,7 +353,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().BeNull(); @@ -362,34 +362,34 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Links.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Links.Should().NotBeNull(); string albumLink = $"{HostPrefix}{PathPrefix}/photoAlbums/{responseDocument.Data.SingleValue.Id}"; responseDocument.Data.SingleValue.Links.Self.Should().Be(albumLink); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("photos").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("photos").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{albumLink}/relationships/photos"); value.Links.Related.Should().Be($"{albumLink}/photos"); }); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].With(resource => { string photoLink = $"{HostPrefix}{PathPrefix}/photos/{existingPhoto.StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(photoLink); - resource.Relationships.ShouldContainKey("album").With(value => + resource.Relationships.Should().ContainKey("album").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{photoLink}/relationships/album"); value.Links.Related.Should().Be($"{photoLink}/album"); }); @@ -402,8 +402,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Update_resource_with_side_effects_and_include_returns_absolute_links() { // Arrange - Photo existingPhoto = _fakers.Photo.Generate(); - PhotoAlbum existingAlbum = _fakers.PhotoAlbum.Generate(); + Photo existingPhoto = _fakers.Photo.GenerateOne(); + PhotoAlbum existingAlbum = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -439,7 +439,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().BeNull(); @@ -450,31 +450,31 @@ await _testContext.RunOnDatabaseAsync(async dbContext => string photoLink = $"{HostPrefix}{PathPrefix}/photos/{existingPhoto.StringId}"; - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Links.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Links.Should().NotBeNull(); responseDocument.Data.SingleValue.Links.Self.Should().Be(photoLink); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("album").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("album").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{photoLink}/relationships/album"); value.Links.Related.Should().Be($"{photoLink}/album"); }); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].With(resource => { string albumLink = $"{HostPrefix}{PathPrefix}/photoAlbums/{existingAlbum.StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(albumLink); - resource.Relationships.ShouldContainKey("photos").With(value => + resource.Relationships.Should().ContainKey("photos").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{albumLink}/relationships/photos"); value.Links.Related.Should().Be($"{albumLink}/photos"); }); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/AbsoluteLinksWithoutNamespaceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/AbsoluteLinksWithoutNamespaceTests.cs index 6efcf034fa..5098e9d34f 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/AbsoluteLinksWithoutNamespaceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/AbsoluteLinksWithoutNamespaceTests.cs @@ -35,7 +35,7 @@ public AbsoluteLinksWithoutNamespaceTests(IntegrationTestContext { @@ -51,7 +51,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().BeNull(); @@ -60,14 +60,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Links.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Links.Should().NotBeNull(); responseDocument.Data.SingleValue.Links.Self.Should().Be($"{HostPrefix}{route}"); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("photos").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("photos").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{HostPrefix}{route}/relationships/photos"); value.Links.Related.Should().Be($"{HostPrefix}{route}/photos"); }); @@ -77,8 +77,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_primary_resources_with_include_returns_absolute_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -95,7 +95,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().Be(responseDocument.Links.Self); @@ -104,37 +104,37 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].With(resource => { string albumLink = $"{HostPrefix}{PathPrefix}/photoAlbums/{album.StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(albumLink); - resource.Relationships.ShouldContainKey("photos").With(value => + resource.Relationships.Should().ContainKey("photos").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{albumLink}/relationships/photos"); value.Links.Related.Should().Be($"{albumLink}/photos"); }); }); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].With(resource => { string photoLink = $"{HostPrefix}{PathPrefix}/photos/{album.Photos.ElementAt(0).StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(photoLink); - resource.Relationships.ShouldContainKey("album").With(value => + resource.Relationships.Should().ContainKey("album").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{photoLink}/relationships/album"); value.Links.Related.Should().Be($"{photoLink}/album"); }); @@ -145,8 +145,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resource_returns_absolute_links() { // Arrange - Photo photo = _fakers.Photo.Generate(); - photo.Album = _fakers.PhotoAlbum.Generate(); + Photo photo = _fakers.Photo.GenerateOne(); + photo.Album = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -162,7 +162,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().BeNull(); @@ -173,14 +173,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => string albumLink = $"{HostPrefix}{PathPrefix}/photoAlbums/{photo.Album.StringId}"; - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Links.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Links.Should().NotBeNull(); responseDocument.Data.SingleValue.Links.Self.Should().Be(albumLink); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("photos").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("photos").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{albumLink}/relationships/photos"); value.Links.Related.Should().Be($"{albumLink}/photos"); }); @@ -190,8 +190,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resources_returns_absolute_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -207,7 +207,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().Be(responseDocument.Links.Self); @@ -216,19 +216,19 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].With(resource => { string photoLink = $"{HostPrefix}{PathPrefix}/photos/{album.Photos.ElementAt(0).StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(photoLink); - resource.Relationships.ShouldContainKey("album").With(value => + resource.Relationships.Should().ContainKey("album").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{photoLink}/relationships/album"); value.Links.Related.Should().Be($"{photoLink}/album"); }); @@ -239,8 +239,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_ToOne_relationship_returns_absolute_links() { // Arrange - Photo photo = _fakers.Photo.Generate(); - photo.Album = _fakers.PhotoAlbum.Generate(); + Photo photo = _fakers.Photo.GenerateOne(); + photo.Album = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -256,7 +256,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().Be($"{HostPrefix}{PathPrefix}/photos/{photo.StringId}/album"); responseDocument.Links.First.Should().BeNull(); @@ -265,7 +265,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Links.Should().BeNull(); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); } @@ -274,8 +274,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_ToMany_relationship_returns_absolute_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -291,7 +291,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().Be($"{HostPrefix}{PathPrefix}/photoAlbums/{album.StringId}/photos"); responseDocument.Links.First.Should().Be(responseDocument.Links.Self); @@ -300,7 +300,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Links.Should().BeNull(); responseDocument.Data.ManyValue[0].Relationships.Should().BeNull(); } @@ -309,9 +309,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Create_resource_with_side_effects_and_include_returns_absolute_links() { // Arrange - Photo existingPhoto = _fakers.Photo.Generate(); + Photo existingPhoto = _fakers.Photo.GenerateOne(); - string newAlbumName = _fakers.PhotoAlbum.Generate().Name; + string newAlbumName = _fakers.PhotoAlbum.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -353,7 +353,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().BeNull(); @@ -362,34 +362,34 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Links.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Links.Should().NotBeNull(); string albumLink = $"{HostPrefix}{PathPrefix}/photoAlbums/{responseDocument.Data.SingleValue.Id}"; responseDocument.Data.SingleValue.Links.Self.Should().Be(albumLink); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("photos").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("photos").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{albumLink}/relationships/photos"); value.Links.Related.Should().Be($"{albumLink}/photos"); }); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].With(resource => { string photoLink = $"{HostPrefix}{PathPrefix}/photos/{existingPhoto.StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(photoLink); - resource.Relationships.ShouldContainKey("album").With(value => + resource.Relationships.Should().ContainKey("album").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{photoLink}/relationships/album"); value.Links.Related.Should().Be($"{photoLink}/album"); }); @@ -402,8 +402,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Update_resource_with_side_effects_and_include_returns_absolute_links() { // Arrange - Photo existingPhoto = _fakers.Photo.Generate(); - PhotoAlbum existingAlbum = _fakers.PhotoAlbum.Generate(); + Photo existingPhoto = _fakers.Photo.GenerateOne(); + PhotoAlbum existingAlbum = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -439,7 +439,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().BeNull(); @@ -450,31 +450,31 @@ await _testContext.RunOnDatabaseAsync(async dbContext => string photoLink = $"{HostPrefix}{PathPrefix}/photos/{existingPhoto.StringId}"; - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Links.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Links.Should().NotBeNull(); responseDocument.Data.SingleValue.Links.Self.Should().Be(photoLink); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("album").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("album").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{photoLink}/relationships/album"); value.Links.Related.Should().Be($"{photoLink}/album"); }); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].With(resource => { string albumLink = $"{HostPrefix}{PathPrefix}/photoAlbums/{existingAlbum.StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(albumLink); - resource.Relationships.ShouldContainKey("photos").With(value => + resource.Relationships.Should().ContainKey("photos").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{albumLink}/relationships/photos"); value.Links.Related.Should().Be($"{albumLink}/photos"); }); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/DocumentDescriptionLinkTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/DocumentDescriptionLinkTests.cs index a2183247e5..99da94cb2c 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/DocumentDescriptionLinkTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/DocumentDescriptionLinkTests.cs @@ -40,7 +40,7 @@ public async Task Get_primary_resource_by_ID_converts_relative_documentation_lin // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.DescribedBy.Should().Be("http://localhost/description/json-schema?version=v1.0"); } @@ -62,7 +62,7 @@ public async Task Get_primary_resource_by_ID_converts_absolute_documentation_lin // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.DescribedBy.Should().Be("description/json-schema?version=v1.0"); } @@ -84,7 +84,7 @@ public async Task Get_primary_resource_by_ID_cannot_convert_absolute_documentati // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.DescribedBy.Should().Be("https://docs.api.com/description/json-schema?version=v1.0"); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinkInclusionIncludeTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinkInclusionIncludeTests.cs index 6b11fb5403..bfaac74209 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinkInclusionIncludeTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinkInclusionIncludeTests.cs @@ -22,9 +22,9 @@ public LinkInclusionIncludeTests(IntegrationTestContext { @@ -40,15 +40,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("photo").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("photo").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); }); - responseDocument.Included.ShouldHaveCount(2); + responseDocument.Included.Should().HaveCount(2); responseDocument.Included.Should().ContainSingle(resource => resource.Type == "photos").Subject.With(resource => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinkInclusionTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinkInclusionTests.cs index 1405d648f2..32fecc526c 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinkInclusionTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinkInclusionTests.cs @@ -24,9 +24,9 @@ public LinkInclusionTests(IntegrationTestContext public async Task Get_primary_resource_with_include_applies_links_visibility_from_ResourceLinksAttribute() { // Arrange - PhotoLocation location = _fakers.PhotoLocation.Generate(); - location.Photo = _fakers.Photo.Generate(); - location.Album = _fakers.PhotoAlbum.Generate(); + PhotoLocation location = _fakers.PhotoLocation.GenerateOne(); + location.Photo = _fakers.Photo.GenerateOne(); + location.Album = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -44,50 +44,50 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Should().BeNull(); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Links.Should().BeNull(); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("photo").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("photo").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().BeNull(); - value.Links.Related.ShouldNotBeNull(); + value.Links.Related.Should().NotBeNull(); }); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("album").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("album").WhoseValue.With(value => { - value.ShouldNotBeNull(); + value.Should().NotBeNull(); value.Links.Should().BeNull(); }); - responseDocument.Included.ShouldHaveCount(2); + responseDocument.Included.Should().HaveCount(2); responseDocument.Included[0].With(resource => { - resource.Links.ShouldNotBeNull(); - resource.Links.Self.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); + resource.Links.Self.Should().NotBeNull(); - resource.Relationships.ShouldContainKey("location").With(value => + resource.Relationships.Should().ContainKey("location").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); - value.Links.Self.ShouldNotBeNull(); - value.Links.Related.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); + value.Links.Self.Should().NotBeNull(); + value.Links.Related.Should().NotBeNull(); }); }); responseDocument.Included[1].With(resource => { - resource.Links.ShouldNotBeNull(); - resource.Links.Self.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); + resource.Links.Self.Should().NotBeNull(); - resource.Relationships.ShouldContainKey("photos").With(value => + resource.Relationships.Should().ContainKey("photos").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); - value.Links.Self.ShouldNotBeNull(); - value.Links.Related.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); + value.Links.Self.Should().NotBeNull(); + value.Links.Related.Should().NotBeNull(); }); }); } @@ -96,8 +96,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resource_applies_links_visibility_from_ResourceLinksAttribute() { // Arrange - Photo photo = _fakers.Photo.Generate(); - photo.Location = _fakers.PhotoLocation.Generate(); + Photo photo = _fakers.Photo.GenerateOne(); + photo.Location = _fakers.PhotoLocation.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -115,15 +115,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Should().BeNull(); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Links.Should().BeNull(); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("photo").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("photo").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().BeNull(); - value.Links.Related.ShouldNotBeNull(); + value.Links.Related.Should().NotBeNull(); }); responseDocument.Data.SingleValue.Relationships.Should().NotContainKey("album"); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinksDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinksDbContext.cs index 9ac46d3b91..4e1cbb29a4 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinksDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/LinksDbContext.cs @@ -7,7 +7,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.Links; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class LinksDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class LinksDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet PhotoAlbums => Set(); public DbSet Photos => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithNamespaceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithNamespaceTests.cs index fbb642844f..60471032e6 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithNamespaceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithNamespaceTests.cs @@ -35,7 +35,7 @@ public RelativeLinksWithNamespaceTests(IntegrationTestContext { @@ -51,7 +51,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().BeNull(); @@ -60,14 +60,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Links.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Links.Should().NotBeNull(); responseDocument.Data.SingleValue.Links.Self.Should().Be($"{HostPrefix}{route}"); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("photos").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("photos").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{HostPrefix}{route}/relationships/photos"); value.Links.Related.Should().Be($"{HostPrefix}{route}/photos"); }); @@ -77,8 +77,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_primary_resources_with_include_returns_relative_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -95,7 +95,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().Be(responseDocument.Links.Self); @@ -104,37 +104,37 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].With(resource => { string albumLink = $"{HostPrefix}{PathPrefix}/photoAlbums/{album.StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(albumLink); - resource.Relationships.ShouldContainKey("photos").With(value => + resource.Relationships.Should().ContainKey("photos").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{albumLink}/relationships/photos"); value.Links.Related.Should().Be($"{albumLink}/photos"); }); }); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].With(resource => { string photoLink = $"{HostPrefix}{PathPrefix}/photos/{album.Photos.ElementAt(0).StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(photoLink); - resource.Relationships.ShouldContainKey("album").With(value => + resource.Relationships.Should().ContainKey("album").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{photoLink}/relationships/album"); value.Links.Related.Should().Be($"{photoLink}/album"); }); @@ -145,8 +145,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resource_returns_relative_links() { // Arrange - Photo photo = _fakers.Photo.Generate(); - photo.Album = _fakers.PhotoAlbum.Generate(); + Photo photo = _fakers.Photo.GenerateOne(); + photo.Album = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -162,7 +162,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().BeNull(); @@ -173,14 +173,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => string albumLink = $"{HostPrefix}{PathPrefix}/photoAlbums/{photo.Album.StringId}"; - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Links.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Links.Should().NotBeNull(); responseDocument.Data.SingleValue.Links.Self.Should().Be(albumLink); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("photos").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("photos").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{albumLink}/relationships/photos"); value.Links.Related.Should().Be($"{albumLink}/photos"); }); @@ -190,8 +190,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resources_returns_relative_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -207,7 +207,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().Be(responseDocument.Links.Self); @@ -216,19 +216,19 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].With(resource => { string photoLink = $"{HostPrefix}{PathPrefix}/photos/{album.Photos.ElementAt(0).StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(photoLink); - resource.Relationships.ShouldContainKey("album").With(value => + resource.Relationships.Should().ContainKey("album").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{photoLink}/relationships/album"); value.Links.Related.Should().Be($"{photoLink}/album"); }); @@ -239,8 +239,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_ToOne_relationship_returns_relative_links() { // Arrange - Photo photo = _fakers.Photo.Generate(); - photo.Album = _fakers.PhotoAlbum.Generate(); + Photo photo = _fakers.Photo.GenerateOne(); + photo.Album = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -256,7 +256,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().Be($"{HostPrefix}{PathPrefix}/photos/{photo.StringId}/album"); responseDocument.Links.First.Should().BeNull(); @@ -265,7 +265,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Links.Should().BeNull(); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); } @@ -274,8 +274,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_ToMany_relationship_returns_relative_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -291,7 +291,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().Be($"{HostPrefix}{PathPrefix}/photoAlbums/{album.StringId}/photos"); responseDocument.Links.First.Should().Be(responseDocument.Links.Self); @@ -300,7 +300,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Links.Should().BeNull(); responseDocument.Data.ManyValue[0].Relationships.Should().BeNull(); } @@ -309,9 +309,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Create_resource_with_side_effects_and_include_returns_relative_links() { // Arrange - Photo existingPhoto = _fakers.Photo.Generate(); + Photo existingPhoto = _fakers.Photo.GenerateOne(); - string newAlbumName = _fakers.PhotoAlbum.Generate().Name; + string newAlbumName = _fakers.PhotoAlbum.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -353,7 +353,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().BeNull(); @@ -362,34 +362,34 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Links.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Links.Should().NotBeNull(); string albumLink = $"{HostPrefix}{PathPrefix}/photoAlbums/{responseDocument.Data.SingleValue.Id}"; responseDocument.Data.SingleValue.Links.Self.Should().Be(albumLink); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("photos").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("photos").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{albumLink}/relationships/photos"); value.Links.Related.Should().Be($"{albumLink}/photos"); }); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].With(resource => { string photoLink = $"{HostPrefix}{PathPrefix}/photos/{existingPhoto.StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(photoLink); - resource.Relationships.ShouldContainKey("album").With(value => + resource.Relationships.Should().ContainKey("album").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{photoLink}/relationships/album"); value.Links.Related.Should().Be($"{photoLink}/album"); }); @@ -402,8 +402,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Update_resource_with_side_effects_and_include_returns_relative_links() { // Arrange - Photo existingPhoto = _fakers.Photo.Generate(); - PhotoAlbum existingAlbum = _fakers.PhotoAlbum.Generate(); + Photo existingPhoto = _fakers.Photo.GenerateOne(); + PhotoAlbum existingAlbum = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -439,7 +439,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().BeNull(); @@ -450,31 +450,31 @@ await _testContext.RunOnDatabaseAsync(async dbContext => string photoLink = $"{HostPrefix}{PathPrefix}/photos/{existingPhoto.StringId}"; - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Links.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Links.Should().NotBeNull(); responseDocument.Data.SingleValue.Links.Self.Should().Be(photoLink); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("album").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("album").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{photoLink}/relationships/album"); value.Links.Related.Should().Be($"{photoLink}/album"); }); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].With(resource => { string albumLink = $"{HostPrefix}{PathPrefix}/photoAlbums/{existingAlbum.StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(albumLink); - resource.Relationships.ShouldContainKey("photos").With(value => + resource.Relationships.Should().ContainKey("photos").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{albumLink}/relationships/photos"); value.Links.Related.Should().Be($"{albumLink}/photos"); }); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithoutNamespaceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithoutNamespaceTests.cs index f767b0cca6..bbb95668d8 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithoutNamespaceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithoutNamespaceTests.cs @@ -35,7 +35,7 @@ public RelativeLinksWithoutNamespaceTests(IntegrationTestContext { @@ -51,7 +51,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().BeNull(); @@ -60,14 +60,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Links.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Links.Should().NotBeNull(); responseDocument.Data.SingleValue.Links.Self.Should().Be($"{HostPrefix}{route}"); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("photos").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("photos").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{HostPrefix}{route}/relationships/photos"); value.Links.Related.Should().Be($"{HostPrefix}{route}/photos"); }); @@ -77,8 +77,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_primary_resources_with_include_returns_relative_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -95,7 +95,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().Be(responseDocument.Links.Self); @@ -104,37 +104,37 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].With(resource => { string albumLink = $"{HostPrefix}{PathPrefix}/photoAlbums/{album.StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(albumLink); - resource.Relationships.ShouldContainKey("photos").With(value => + resource.Relationships.Should().ContainKey("photos").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{albumLink}/relationships/photos"); value.Links.Related.Should().Be($"{albumLink}/photos"); }); }); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].With(resource => { string photoLink = $"{HostPrefix}{PathPrefix}/photos/{album.Photos.ElementAt(0).StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(photoLink); - resource.Relationships.ShouldContainKey("album").With(value => + resource.Relationships.Should().ContainKey("album").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{photoLink}/relationships/album"); value.Links.Related.Should().Be($"{photoLink}/album"); }); @@ -145,8 +145,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resource_returns_relative_links() { // Arrange - Photo photo = _fakers.Photo.Generate(); - photo.Album = _fakers.PhotoAlbum.Generate(); + Photo photo = _fakers.Photo.GenerateOne(); + photo.Album = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -162,7 +162,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().BeNull(); @@ -173,14 +173,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => string albumLink = $"{HostPrefix}{PathPrefix}/photoAlbums/{photo.Album.StringId}"; - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Links.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Links.Should().NotBeNull(); responseDocument.Data.SingleValue.Links.Self.Should().Be(albumLink); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("photos").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("photos").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{albumLink}/relationships/photos"); value.Links.Related.Should().Be($"{albumLink}/photos"); }); @@ -190,8 +190,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resources_returns_relative_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -207,7 +207,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().Be(responseDocument.Links.Self); @@ -216,19 +216,19 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].With(resource => { string photoLink = $"{HostPrefix}{PathPrefix}/photos/{album.Photos.ElementAt(0).StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(photoLink); - resource.Relationships.ShouldContainKey("album").With(value => + resource.Relationships.Should().ContainKey("album").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{photoLink}/relationships/album"); value.Links.Related.Should().Be($"{photoLink}/album"); }); @@ -239,8 +239,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_ToOne_relationship_returns_relative_links() { // Arrange - Photo photo = _fakers.Photo.Generate(); - photo.Album = _fakers.PhotoAlbum.Generate(); + Photo photo = _fakers.Photo.GenerateOne(); + photo.Album = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -256,7 +256,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().Be($"{HostPrefix}{PathPrefix}/photos/{photo.StringId}/album"); responseDocument.Links.First.Should().BeNull(); @@ -265,7 +265,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Links.Should().BeNull(); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); } @@ -274,8 +274,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_ToMany_relationship_returns_relative_links() { // Arrange - PhotoAlbum album = _fakers.PhotoAlbum.Generate(); - album.Photos = _fakers.Photo.Generate(1).ToHashSet(); + PhotoAlbum album = _fakers.PhotoAlbum.GenerateOne(); + album.Photos = _fakers.Photo.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -291,7 +291,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().Be($"{HostPrefix}{PathPrefix}/photoAlbums/{album.StringId}/photos"); responseDocument.Links.First.Should().Be(responseDocument.Links.Self); @@ -300,7 +300,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Links.Should().BeNull(); responseDocument.Data.ManyValue[0].Relationships.Should().BeNull(); } @@ -309,9 +309,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Create_resource_with_side_effects_and_include_returns_relative_links() { // Arrange - Photo existingPhoto = _fakers.Photo.Generate(); + Photo existingPhoto = _fakers.Photo.GenerateOne(); - string newAlbumName = _fakers.PhotoAlbum.Generate().Name; + string newAlbumName = _fakers.PhotoAlbum.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -353,7 +353,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().BeNull(); @@ -362,34 +362,34 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Next.Should().BeNull(); responseDocument.Links.DescribedBy.Should().BeNull(); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Links.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Links.Should().NotBeNull(); string albumLink = $"{HostPrefix}{PathPrefix}/photoAlbums/{responseDocument.Data.SingleValue.Id}"; responseDocument.Data.SingleValue.Links.Self.Should().Be(albumLink); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("photos").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("photos").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{albumLink}/relationships/photos"); value.Links.Related.Should().Be($"{albumLink}/photos"); }); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].With(resource => { string photoLink = $"{HostPrefix}{PathPrefix}/photos/{existingPhoto.StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(photoLink); - resource.Relationships.ShouldContainKey("album").With(value => + resource.Relationships.Should().ContainKey("album").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{photoLink}/relationships/album"); value.Links.Related.Should().Be($"{photoLink}/album"); }); @@ -402,8 +402,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Update_resource_with_side_effects_and_include_returns_relative_links() { // Arrange - Photo existingPhoto = _fakers.Photo.Generate(); - PhotoAlbum existingAlbum = _fakers.PhotoAlbum.Generate(); + Photo existingPhoto = _fakers.Photo.GenerateOne(); + PhotoAlbum existingAlbum = _fakers.PhotoAlbum.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -439,7 +439,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().BeNull(); @@ -450,31 +450,31 @@ await _testContext.RunOnDatabaseAsync(async dbContext => string photoLink = $"{HostPrefix}{PathPrefix}/photos/{existingPhoto.StringId}"; - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Links.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Links.Should().NotBeNull(); responseDocument.Data.SingleValue.Links.Self.Should().Be(photoLink); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("album").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("album").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{photoLink}/relationships/album"); value.Links.Related.Should().Be($"{photoLink}/album"); }); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].With(resource => { string albumLink = $"{HostPrefix}{PathPrefix}/photoAlbums/{existingAlbum.StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(albumLink); - resource.Relationships.ShouldContainKey("photos").With(value => + resource.Relationships.Should().ContainKey("photos").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{albumLink}/relationships/photos"); value.Links.Related.Should().Be($"{albumLink}/photos"); }); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Logging/LoggingDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Logging/LoggingDbContext.cs index 262f8e1aee..63a58d20b5 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Logging/LoggingDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Logging/LoggingDbContext.cs @@ -5,7 +5,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.Logging; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class LoggingDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class LoggingDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet AuditEntries => Set(); public DbSet FruitBowls => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Logging/LoggingTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Logging/LoggingTests.cs index cc56c3980f..9fbd9e8051 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Logging/LoggingTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Logging/LoggingTests.cs @@ -20,27 +20,26 @@ public LoggingTests(IntegrationTestContext, Lo testContext.UseController(); testContext.UseController(); - var loggerFactory = new FakeLoggerFactory(LogLevel.Trace); - testContext.ConfigureLogging(options => { - options.ClearProviders(); - options.AddProvider(loggerFactory); + var loggerProvider = new CapturingLoggerProvider((category, level) => + level >= LogLevel.Trace && category.StartsWith("JsonApiDotNetCore.", StringComparison.Ordinal)); + + options.AddProvider(loggerProvider); options.SetMinimumLevel(LogLevel.Trace); - options.AddFilter((category, _) => category != null && category.StartsWith("JsonApiDotNetCore.", StringComparison.Ordinal)); - }); - testContext.ConfigureServices(services => services.AddSingleton(loggerFactory)); + options.Services.AddSingleton(loggerProvider); + }); } [Fact] public async Task Logs_request_body_at_Trace_level() { // Arrange - var loggerFactory = _testContext.Factory.Services.GetRequiredService(); - loggerFactory.Logger.Clear(); + var loggerProvider = _testContext.Factory.Services.GetRequiredService(); + loggerProvider.Clear(); - AuditEntry newEntry = _fakers.AuditEntry.Generate(); + AuditEntry newEntry = _fakers.AuditEntry.GenerateOne(); var requestBody = new { @@ -64,8 +63,7 @@ public async Task Logs_request_body_at_Trace_level() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - IReadOnlyList logLines = loggerFactory.Logger.GetLines(); - logLines.ShouldNotBeEmpty(); + IReadOnlyList logLines = loggerProvider.GetLines(); logLines.Should().ContainSingle(line => line.StartsWith("[TRACE] Received POST request at 'http://localhost/auditEntries' with body: <<", StringComparison.Ordinal)); @@ -75,8 +73,8 @@ public async Task Logs_request_body_at_Trace_level() public async Task Logs_response_body_at_Trace_level() { // Arrange - var loggerFactory = _testContext.Factory.Services.GetRequiredService(); - loggerFactory.Logger.Clear(); + var loggerProvider = _testContext.Factory.Services.GetRequiredService(); + loggerProvider.Clear(); // Arrange const string route = "/auditEntries"; @@ -87,8 +85,7 @@ public async Task Logs_response_body_at_Trace_level() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - IReadOnlyList logLines = loggerFactory.Logger.GetLines(); - logLines.ShouldNotBeEmpty(); + IReadOnlyList logLines = loggerProvider.GetLines(); logLines.Should().ContainSingle(line => line.StartsWith("[TRACE] Sending 200 response for GET request at 'http://localhost/auditEntries' with body: <<", StringComparison.Ordinal)); @@ -98,8 +95,8 @@ public async Task Logs_response_body_at_Trace_level() public async Task Logs_invalid_request_body_error_at_Information_level() { // Arrange - var loggerFactory = _testContext.Factory.Services.GetRequiredService(); - loggerFactory.Logger.Clear(); + var loggerProvider = _testContext.Factory.Services.GetRequiredService(); + loggerProvider.Clear(); // Arrange const string requestBody = "{ \"data\" {"; @@ -112,21 +109,19 @@ public async Task Logs_invalid_request_body_error_at_Information_level() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - IReadOnlyList logMessages = loggerFactory.Logger.GetMessages(); - logMessages.ShouldNotBeEmpty(); - - logMessages.Should().ContainSingle(message => message.LogLevel == LogLevel.Information && message.Text.Contains("Failed to deserialize request body.")); + LogMessage[] infoMessages = loggerProvider.GetMessages().Where(message => message.LogLevel == LogLevel.Information).ToArray(); + infoMessages.Should().ContainSingle(message => message.Text.Contains("Failed to deserialize request body.")); } [Fact] public async Task Logs_method_parameters_of_abstract_resource_type_at_Trace_level() { // Arrange - var loggerFactory = _testContext.Factory.Services.GetRequiredService(); - loggerFactory.Logger.Clear(); + var loggerProvider = _testContext.Factory.Services.GetRequiredService(); + loggerProvider.Clear(); var existingBowl = new FruitBowl(); - Banana existingBanana = _fakers.Banana.Generate(); + Banana existingBanana = _fakers.Banana.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -157,7 +152,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Should().BeEmpty(); - IReadOnlyList logLines = loggerFactory.Logger.GetLines(); + IReadOnlyList logLines = loggerProvider.GetLines(); logLines.Should().BeEquivalentTo(new[] { @@ -232,11 +227,11 @@ [TRACE] Entering AddToToManyRelationshipAsync(leftResource: null, leftId: {{exis public async Task Logs_method_parameters_of_concrete_resource_type_at_Trace_level() { // Arrange - var loggerFactory = _testContext.Factory.Services.GetRequiredService(); - loggerFactory.Logger.Clear(); + var loggerProvider = _testContext.Factory.Services.GetRequiredService(); + loggerProvider.Clear(); var existingBowl = new FruitBowl(); - Peach existingPeach = _fakers.Peach.Generate(); + Peach existingPeach = _fakers.Peach.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -267,7 +262,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Should().BeEmpty(); - IReadOnlyList logLines = loggerFactory.Logger.GetLines(); + IReadOnlyList logLines = loggerProvider.GetLines(); logLines.Should().BeEquivalentTo(new[] { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/MetaDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/MetaDbContext.cs index a1ab87c420..6e0b13afa5 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/MetaDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/MetaDbContext.cs @@ -5,7 +5,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.Meta; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class MetaDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class MetaDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet ProductFamilies => Set(); public DbSet SupportTickets => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/ResourceMetaTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/ResourceMetaTests.cs index 230bdd8b23..f160c21068 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/ResourceMetaTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/ResourceMetaTests.cs @@ -37,7 +37,7 @@ public async Task Returns_resource_meta_from_ResourceDefinition() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - List tickets = _fakers.SupportTicket.Generate(3); + List tickets = _fakers.SupportTicket.GenerateList(3); tickets[0].Description = $"Critical: {tickets[0].Description}"; tickets[2].Description = $"Critical: {tickets[2].Description}"; @@ -56,10 +56,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(3); - responseDocument.Data.ManyValue[0].Meta.ShouldContainKey("hasHighPriority"); + responseDocument.Data.ManyValue.Should().HaveCount(3); + responseDocument.Data.ManyValue[0].Meta.Should().ContainKey("hasHighPriority"); responseDocument.Data.ManyValue[1].Meta.Should().BeNull(); - responseDocument.Data.ManyValue[2].Meta.ShouldContainKey("hasHighPriority"); + responseDocument.Data.ManyValue[2].Meta.Should().ContainKey("hasHighPriority"); hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] { @@ -75,8 +75,8 @@ public async Task Returns_resource_meta_from_ResourceDefinition_in_included_reso // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - ProductFamily family = _fakers.ProductFamily.Generate(); - family.Tickets = _fakers.SupportTicket.Generate(1); + ProductFamily family = _fakers.ProductFamily.GenerateOne(); + family.Tickets = _fakers.SupportTicket.GenerateList(1); family.Tickets[0].Description = $"Critical: {family.Tickets[0].Description}"; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -94,9 +94,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Included.ShouldHaveCount(1); - responseDocument.Included[0].Meta.ShouldContainKey("hasHighPriority"); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Included.Should().HaveCount(1); + responseDocument.Included[0].Meta.Should().ContainKey("hasHighPriority"); hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/TopLevelCountTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/TopLevelCountTests.cs index d074c87160..5a72d4af80 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/TopLevelCountTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/TopLevelCountTests.cs @@ -31,7 +31,7 @@ public TopLevelCountTests(IntegrationTestContext, public async Task Renders_resource_count_at_primary_resources_endpoint_with_filter() { // Arrange - List tickets = _fakers.SupportTicket.Generate(2); + List tickets = _fakers.SupportTicket.GenerateList(2); tickets[1].Description = "Update firmware version"; @@ -57,8 +57,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Renders_resource_count_at_secondary_resources_endpoint_with_filter() { // Arrange - ProductFamily family = _fakers.ProductFamily.Generate(); - family.Tickets = _fakers.SupportTicket.Generate(2); + ProductFamily family = _fakers.ProductFamily.GenerateOne(); + family.Tickets = _fakers.SupportTicket.GenerateList(2); family.Tickets[1].Description = "Update firmware version"; @@ -103,7 +103,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Hides_resource_count_in_create_resource_response() { // Arrange - string newDescription = _fakers.SupportTicket.Generate().Description; + string newDescription = _fakers.SupportTicket.GenerateOne().Description; var requestBody = new { @@ -132,9 +132,9 @@ public async Task Hides_resource_count_in_create_resource_response() public async Task Hides_resource_count_in_update_resource_response() { // Arrange - SupportTicket existingTicket = _fakers.SupportTicket.Generate(); + SupportTicket existingTicket = _fakers.SupportTicket.GenerateOne(); - string newDescription = _fakers.SupportTicket.Generate().Description; + string newDescription = _fakers.SupportTicket.GenerateOne().Description; await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetDbContext.cs index c25715d282..b310d9d062 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetDbContext.cs @@ -5,7 +5,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.Microservices.FireAndForgetDelivery; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class FireForgetDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class FireForgetDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet Users => Set(); public DbSet Groups => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.Group.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.Group.cs index 7421c06256..a412d64d96 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.Group.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.Group.cs @@ -17,7 +17,7 @@ public async Task Create_group_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - string newGroupName = _fakers.DomainGroup.Generate().Name; + string newGroupName = _fakers.DomainGroup.GenerateOne().Name; var requestBody = new { @@ -39,8 +39,8 @@ public async Task Create_group_sends_messages() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("name").With(value => value.Should().Be(newGroupName)); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(newGroupName); hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] { @@ -49,9 +49,9 @@ public async Task Create_group_sends_messages() (typeof(DomainGroup), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - messageBroker.SentMessages.ShouldHaveCount(1); + messageBroker.SentMessages.Should().HaveCount(1); - Guid newGroupId = Guid.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + Guid newGroupId = Guid.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); var content = messageBroker.SentMessages[0].GetContentAs(); content.GroupId.Should().Be(newGroupId); @@ -65,12 +65,12 @@ public async Task Create_group_with_users_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUserWithoutGroup = _fakers.DomainUser.Generate(); + DomainUser existingUserWithoutGroup = _fakers.DomainUser.GenerateOne(); - DomainUser existingUserWithOtherGroup = _fakers.DomainUser.Generate(); - existingUserWithOtherGroup.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUserWithOtherGroup = _fakers.DomainUser.GenerateOne(); + existingUserWithOtherGroup.Group = _fakers.DomainGroup.GenerateOne(); - string newGroupName = _fakers.DomainGroup.Generate().Name; + string newGroupName = _fakers.DomainGroup.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -117,8 +117,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("name").With(value => value.Should().Be(newGroupName)); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(newGroupName); hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] { @@ -128,9 +128,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => (typeof(DomainGroup), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - messageBroker.SentMessages.ShouldHaveCount(3); + messageBroker.SentMessages.Should().HaveCount(3); - Guid newGroupId = Guid.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + Guid newGroupId = Guid.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); var content1 = messageBroker.SentMessages[0].GetContentAs(); content1.GroupId.Should().Be(newGroupId); @@ -153,9 +153,9 @@ public async Task Update_group_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - string newGroupName = _fakers.DomainGroup.Generate().Name; + string newGroupName = _fakers.DomainGroup.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -193,7 +193,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => (typeof(DomainGroup), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - messageBroker.SentMessages.ShouldHaveCount(1); + messageBroker.SentMessages.Should().HaveCount(1); var content = messageBroker.SentMessages[0].GetContentAs(); content.GroupId.Should().Be(existingGroup.StringId); @@ -208,18 +208,18 @@ public async Task Update_group_with_users_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - DomainUser existingUserWithoutGroup = _fakers.DomainUser.Generate(); + DomainUser existingUserWithoutGroup = _fakers.DomainUser.GenerateOne(); - DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup1.Group = existingGroup; - DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup2.Group = existingGroup; - DomainUser existingUserWithOtherGroup = _fakers.DomainUser.Generate(); - existingUserWithOtherGroup.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUserWithOtherGroup = _fakers.DomainUser.GenerateOne(); + existingUserWithOtherGroup.Group = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -278,7 +278,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => (typeof(DomainGroup), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - messageBroker.SentMessages.ShouldHaveCount(3); + messageBroker.SentMessages.Should().HaveCount(3); var content1 = messageBroker.SentMessages[0].GetContentAs(); content1.UserId.Should().Be(existingUserWithoutGroup.Id); @@ -301,7 +301,7 @@ public async Task Delete_group_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -325,7 +325,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => (typeof(DomainGroup), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - messageBroker.SentMessages.ShouldHaveCount(1); + messageBroker.SentMessages.Should().HaveCount(1); var content = messageBroker.SentMessages[0].GetContentAs(); content.GroupId.Should().Be(existingGroup.StringId); @@ -338,8 +338,8 @@ public async Task Delete_group_with_users_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); - existingGroup.Users = _fakers.DomainUser.Generate(1).ToHashSet(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); + existingGroup.Users = _fakers.DomainUser.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -363,7 +363,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => (typeof(DomainGroup), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - messageBroker.SentMessages.ShouldHaveCount(2); + messageBroker.SentMessages.Should().HaveCount(2); var content1 = messageBroker.SentMessages[0].GetContentAs(); content1.UserId.Should().Be(existingGroup.Users.ElementAt(0).Id); @@ -380,18 +380,18 @@ public async Task Replace_users_in_group_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - DomainUser existingUserWithoutGroup = _fakers.DomainUser.Generate(); + DomainUser existingUserWithoutGroup = _fakers.DomainUser.GenerateOne(); - DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup1.Group = existingGroup; - DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup2.Group = existingGroup; - DomainUser existingUserWithOtherGroup = _fakers.DomainUser.Generate(); - existingUserWithOtherGroup.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUserWithOtherGroup = _fakers.DomainUser.GenerateOne(); + existingUserWithOtherGroup.Group = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -439,7 +439,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => (typeof(DomainGroup), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - messageBroker.SentMessages.ShouldHaveCount(3); + messageBroker.SentMessages.Should().HaveCount(3); var content1 = messageBroker.SentMessages[0].GetContentAs(); content1.UserId.Should().Be(existingUserWithoutGroup.Id); @@ -462,15 +462,15 @@ public async Task Add_users_to_group_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - DomainUser existingUserWithoutGroup = _fakers.DomainUser.Generate(); + DomainUser existingUserWithoutGroup = _fakers.DomainUser.GenerateOne(); - DomainUser existingUserWithSameGroup = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup.Group = existingGroup; - DomainUser existingUserWithOtherGroup = _fakers.DomainUser.Generate(); - existingUserWithOtherGroup.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUserWithOtherGroup = _fakers.DomainUser.GenerateOne(); + existingUserWithOtherGroup.Group = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -512,7 +512,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => (typeof(DomainGroup), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - messageBroker.SentMessages.ShouldHaveCount(2); + messageBroker.SentMessages.Should().HaveCount(2); var content1 = messageBroker.SentMessages[0].GetContentAs(); content1.UserId.Should().Be(existingUserWithoutGroup.Id); @@ -531,12 +531,12 @@ public async Task Remove_users_from_group_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup1.Group = existingGroup; - DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup2.Group = existingGroup; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -575,7 +575,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => (typeof(DomainGroup), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - messageBroker.SentMessages.ShouldHaveCount(1); + messageBroker.SentMessages.Should().HaveCount(1); var content = messageBroker.SentMessages[0].GetContentAs(); content.UserId.Should().Be(existingUserWithSameGroup2.Id); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.User.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.User.cs index 1a53699b03..e8687d9993 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.User.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.User.cs @@ -17,8 +17,8 @@ public async Task Create_user_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - string newLoginName = _fakers.DomainUser.Generate().LoginName; - string newDisplayName = _fakers.DomainUser.Generate().DisplayName!; + string newLoginName = _fakers.DomainUser.GenerateOne().LoginName; + string newDisplayName = _fakers.DomainUser.GenerateOne().DisplayName!; var requestBody = new { @@ -41,9 +41,9 @@ public async Task Create_user_sends_messages() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("loginName").With(value => value.Should().Be(newLoginName)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("displayName").With(value => value.Should().Be(newDisplayName)); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("loginName").WhoseValue.Should().Be(newLoginName); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("displayName").WhoseValue.Should().Be(newDisplayName); hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] { @@ -52,9 +52,9 @@ public async Task Create_user_sends_messages() (typeof(DomainUser), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - messageBroker.SentMessages.ShouldHaveCount(1); + messageBroker.SentMessages.Should().HaveCount(1); - Guid newUserId = Guid.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + Guid newUserId = Guid.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); var content = messageBroker.SentMessages[0].GetContentAs(); content.UserId.Should().Be(newUserId); @@ -69,9 +69,9 @@ public async Task Create_user_in_group_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - string newLoginName = _fakers.DomainUser.Generate().LoginName; + string newLoginName = _fakers.DomainUser.GenerateOne().LoginName; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -110,9 +110,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("loginName").With(value => value.Should().Be(newLoginName)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("displayName").With(value => value.Should().BeNull()); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("loginName").WhoseValue.Should().Be(newLoginName); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("displayName").WhoseValue.Should().BeNull(); hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] { @@ -122,9 +122,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => (typeof(DomainUser), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - messageBroker.SentMessages.ShouldHaveCount(2); + messageBroker.SentMessages.Should().HaveCount(2); - Guid newUserId = Guid.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + Guid newUserId = Guid.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); var content1 = messageBroker.SentMessages[0].GetContentAs(); content1.UserId.Should().Be(newUserId); @@ -143,10 +143,10 @@ public async Task Update_user_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); - string newLoginName = _fakers.DomainUser.Generate().LoginName; - string newDisplayName = _fakers.DomainUser.Generate().DisplayName!; + string newLoginName = _fakers.DomainUser.GenerateOne().LoginName; + string newDisplayName = _fakers.DomainUser.GenerateOne().DisplayName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -185,7 +185,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => (typeof(DomainUser), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - messageBroker.SentMessages.ShouldHaveCount(2); + messageBroker.SentMessages.Should().HaveCount(2); var content1 = messageBroker.SentMessages[0].GetContentAs(); content1.UserId.Should().Be(existingUser.Id); @@ -205,10 +205,10 @@ public async Task Update_user_clear_group_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - existingUser.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + existingUser.Group = _fakers.DomainGroup.GenerateOne(); - string newDisplayName = _fakers.DomainUser.Generate().DisplayName!; + string newDisplayName = _fakers.DomainUser.GenerateOne().DisplayName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -254,7 +254,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => (typeof(DomainUser), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - messageBroker.SentMessages.ShouldHaveCount(2); + messageBroker.SentMessages.Should().HaveCount(2); var content1 = messageBroker.SentMessages[0].GetContentAs(); content1.UserId.Should().Be(existingUser.Id); @@ -273,10 +273,10 @@ public async Task Update_user_add_to_group_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - string newDisplayName = _fakers.DomainUser.Generate().DisplayName!; + string newDisplayName = _fakers.DomainUser.GenerateOne().DisplayName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -326,7 +326,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => (typeof(DomainUser), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - messageBroker.SentMessages.ShouldHaveCount(2); + messageBroker.SentMessages.Should().HaveCount(2); var content1 = messageBroker.SentMessages[0].GetContentAs(); content1.UserId.Should().Be(existingUser.Id); @@ -345,12 +345,12 @@ public async Task Update_user_move_to_group_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - existingUser.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + existingUser.Group = _fakers.DomainGroup.GenerateOne(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - string newDisplayName = _fakers.DomainUser.Generate().DisplayName!; + string newDisplayName = _fakers.DomainUser.GenerateOne().DisplayName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -400,7 +400,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => (typeof(DomainUser), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - messageBroker.SentMessages.ShouldHaveCount(2); + messageBroker.SentMessages.Should().HaveCount(2); var content1 = messageBroker.SentMessages[0].GetContentAs(); content1.UserId.Should().Be(existingUser.Id); @@ -420,7 +420,7 @@ public async Task Delete_user_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -444,7 +444,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => (typeof(DomainUser), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - messageBroker.SentMessages.ShouldHaveCount(1); + messageBroker.SentMessages.Should().HaveCount(1); var content = messageBroker.SentMessages[0].GetContentAs(); content.UserId.Should().Be(existingUser.Id); @@ -457,8 +457,8 @@ public async Task Delete_user_in_group_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - existingUser.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + existingUser.Group = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -482,7 +482,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => (typeof(DomainUser), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - messageBroker.SentMessages.ShouldHaveCount(2); + messageBroker.SentMessages.Should().HaveCount(2); var content1 = messageBroker.SentMessages[0].GetContentAs(); content1.UserId.Should().Be(existingUser.Id); @@ -499,8 +499,8 @@ public async Task Clear_group_from_user_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - existingUser.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + existingUser.Group = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -531,7 +531,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => (typeof(DomainUser), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - messageBroker.SentMessages.ShouldHaveCount(1); + messageBroker.SentMessages.Should().HaveCount(1); var content = messageBroker.SentMessages[0].GetContentAs(); content.UserId.Should().Be(existingUser.Id); @@ -545,8 +545,8 @@ public async Task Assign_group_to_user_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -581,7 +581,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => (typeof(DomainUser), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - messageBroker.SentMessages.ShouldHaveCount(1); + messageBroker.SentMessages.Should().HaveCount(1); var content = messageBroker.SentMessages[0].GetContentAs(); content.UserId.Should().Be(existingUser.Id); @@ -595,10 +595,10 @@ public async Task Replace_group_for_user_sends_messages() var hitCounter = _testContext.Factory.Services.GetRequiredService(); var messageBroker = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - existingUser.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + existingUser.Group = _fakers.DomainGroup.GenerateOne(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -633,7 +633,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => (typeof(DomainUser), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - messageBroker.SentMessages.ShouldHaveCount(1); + messageBroker.SentMessages.Should().HaveCount(1); var content = messageBroker.SentMessages[0].GetContentAs(); content.UserId.Should().Be(existingUser.Id); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.cs index 86456d2d43..b9ed0b5df4 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/FireAndForgetDelivery/FireForgetTests.cs @@ -53,7 +53,7 @@ public async Task Does_not_send_message_on_write_error() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -77,7 +77,7 @@ public async Task Does_not_rollback_on_message_delivery_error() var messageBroker = _testContext.Factory.Services.GetRequiredService(); messageBroker.SimulateFailure = true; - DomainUser existingUser = _fakers.DomainUser.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -94,7 +94,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.ServiceUnavailable); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.ServiceUnavailable); @@ -107,7 +107,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => (typeof(DomainUser), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - messageBroker.SentMessages.ShouldHaveCount(1); + messageBroker.SentMessages.Should().HaveCount(1); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/MessagingGroupDefinition.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/MessagingGroupDefinition.cs index 7c392eaf7a..048206e20f 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/MessagingGroupDefinition.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/MessagingGroupDefinition.cs @@ -53,7 +53,7 @@ public override async Task OnSetToManyRelationshipAsync(DomainGroup group, HasMa { content = new UserAddedToGroupContent(beforeUser.Id, group.Id); } - else if (beforeUser.Group != null && beforeUser.Group.Id != group.Id) + else if (beforeUser.Group.Id != group.Id) { content = new UserMovedToGroupContent(beforeUser.Id, beforeUser.Group.Id, group.Id); } @@ -94,7 +94,7 @@ public override async Task OnAddToRelationshipAsync(DomainGroup group, HasManyAt { content = new UserAddedToGroupContent(beforeUser.Id, group.Id); } - else if (beforeUser.Group != null && beforeUser.Group.Id != group.Id) + else if (beforeUser.Group.Id != group.Id) { content = new UserMovedToGroupContent(beforeUser.Id, beforeUser.Group.Id, group.Id); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxDbContext.cs index a09b8ba389..ce2f82fe3f 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxDbContext.cs @@ -6,7 +6,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.Microservices.TransactionalOutboxPattern; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class OutboxDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class OutboxDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet Users => Set(); public DbSet Groups => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.Group.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.Group.cs index cc5b5e84ab..47c5698e38 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.Group.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.Group.cs @@ -17,7 +17,7 @@ public async Task Create_group_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - string newGroupName = _fakers.DomainGroup.Generate().Name; + string newGroupName = _fakers.DomainGroup.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -44,8 +44,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("name").With(value => value.Should().Be(newGroupName)); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(newGroupName); hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] { @@ -54,12 +54,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => (typeof(DomainGroup), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - Guid newGroupId = Guid.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + Guid newGroupId = Guid.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { List messages = await dbContext.OutboxMessages.OrderBy(message => message.Id).ToListAsync(); - messages.ShouldHaveCount(1); + messages.Should().HaveCount(1); var content = messages[0].GetContentAs(); content.GroupId.Should().Be(newGroupId); @@ -73,12 +73,12 @@ public async Task Create_group_with_users_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUserWithoutGroup = _fakers.DomainUser.Generate(); + DomainUser existingUserWithoutGroup = _fakers.DomainUser.GenerateOne(); - DomainUser existingUserWithOtherGroup = _fakers.DomainUser.Generate(); - existingUserWithOtherGroup.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUserWithOtherGroup = _fakers.DomainUser.GenerateOne(); + existingUserWithOtherGroup.Group = _fakers.DomainGroup.GenerateOne(); - string newGroupName = _fakers.DomainGroup.Generate().Name; + string newGroupName = _fakers.DomainGroup.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -126,8 +126,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("name").With(value => value.Should().Be(newGroupName)); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(newGroupName); hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] { @@ -137,12 +137,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => (typeof(DomainGroup), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - Guid newGroupId = Guid.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + Guid newGroupId = Guid.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { List messages = await dbContext.OutboxMessages.OrderBy(message => message.Id).ToListAsync(); - messages.ShouldHaveCount(3); + messages.Should().HaveCount(3); var content1 = messages[0].GetContentAs(); content1.GroupId.Should().Be(newGroupId); @@ -165,9 +165,9 @@ public async Task Update_group_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - string newGroupName = _fakers.DomainGroup.Generate().Name; + string newGroupName = _fakers.DomainGroup.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -209,7 +209,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => await _testContext.RunOnDatabaseAsync(async dbContext => { List messages = await dbContext.OutboxMessages.OrderBy(message => message.Id).ToListAsync(); - messages.ShouldHaveCount(1); + messages.Should().HaveCount(1); var content = messages[0].GetContentAs(); content.GroupId.Should().Be(existingGroup.StringId); @@ -224,18 +224,18 @@ public async Task Update_group_with_users_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - DomainUser existingUserWithoutGroup = _fakers.DomainUser.Generate(); + DomainUser existingUserWithoutGroup = _fakers.DomainUser.GenerateOne(); - DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup1.Group = existingGroup; - DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup2.Group = existingGroup; - DomainUser existingUserWithOtherGroup = _fakers.DomainUser.Generate(); - existingUserWithOtherGroup.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUserWithOtherGroup = _fakers.DomainUser.GenerateOne(); + existingUserWithOtherGroup.Group = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -298,7 +298,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => await _testContext.RunOnDatabaseAsync(async dbContext => { List messages = await dbContext.OutboxMessages.OrderBy(message => message.Id).ToListAsync(); - messages.ShouldHaveCount(3); + messages.Should().HaveCount(3); var content1 = messages[0].GetContentAs(); content1.UserId.Should().Be(existingUserWithoutGroup.Id); @@ -321,7 +321,7 @@ public async Task Delete_group_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -349,7 +349,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => await _testContext.RunOnDatabaseAsync(async dbContext => { List messages = await dbContext.OutboxMessages.OrderBy(message => message.Id).ToListAsync(); - messages.ShouldHaveCount(1); + messages.Should().HaveCount(1); var content = messages[0].GetContentAs(); content.GroupId.Should().Be(existingGroup.StringId); @@ -362,8 +362,8 @@ public async Task Delete_group_with_users_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); - existingGroup.Users = _fakers.DomainUser.Generate(1).ToHashSet(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); + existingGroup.Users = _fakers.DomainUser.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -391,7 +391,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => await _testContext.RunOnDatabaseAsync(async dbContext => { List messages = await dbContext.OutboxMessages.OrderBy(message => message.Id).ToListAsync(); - messages.ShouldHaveCount(2); + messages.Should().HaveCount(2); var content1 = messages[0].GetContentAs(); content1.UserId.Should().Be(existingGroup.Users.ElementAt(0).Id); @@ -408,18 +408,18 @@ public async Task Replace_users_in_group_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - DomainUser existingUserWithoutGroup = _fakers.DomainUser.Generate(); + DomainUser existingUserWithoutGroup = _fakers.DomainUser.GenerateOne(); - DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup1.Group = existingGroup; - DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup2.Group = existingGroup; - DomainUser existingUserWithOtherGroup = _fakers.DomainUser.Generate(); - existingUserWithOtherGroup.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUserWithOtherGroup = _fakers.DomainUser.GenerateOne(); + existingUserWithOtherGroup.Group = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -471,7 +471,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => await _testContext.RunOnDatabaseAsync(async dbContext => { List messages = await dbContext.OutboxMessages.OrderBy(message => message.Id).ToListAsync(); - messages.ShouldHaveCount(3); + messages.Should().HaveCount(3); var content1 = messages[0].GetContentAs(); content1.UserId.Should().Be(existingUserWithoutGroup.Id); @@ -494,15 +494,15 @@ public async Task Add_users_to_group_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - DomainUser existingUserWithoutGroup = _fakers.DomainUser.Generate(); + DomainUser existingUserWithoutGroup = _fakers.DomainUser.GenerateOne(); - DomainUser existingUserWithSameGroup = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup.Group = existingGroup; - DomainUser existingUserWithOtherGroup = _fakers.DomainUser.Generate(); - existingUserWithOtherGroup.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUserWithOtherGroup = _fakers.DomainUser.GenerateOne(); + existingUserWithOtherGroup.Group = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -548,7 +548,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => await _testContext.RunOnDatabaseAsync(async dbContext => { List messages = await dbContext.OutboxMessages.OrderBy(message => message.Id).ToListAsync(); - messages.ShouldHaveCount(2); + messages.Should().HaveCount(2); var content1 = messages[0].GetContentAs(); content1.UserId.Should().Be(existingUserWithoutGroup.Id); @@ -567,12 +567,12 @@ public async Task Remove_users_from_group_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup1 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup1.Group = existingGroup; - DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.Generate(); + DomainUser existingUserWithSameGroup2 = _fakers.DomainUser.GenerateOne(); existingUserWithSameGroup2.Group = existingGroup; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -615,7 +615,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => await _testContext.RunOnDatabaseAsync(async dbContext => { List messages = await dbContext.OutboxMessages.OrderBy(message => message.Id).ToListAsync(); - messages.ShouldHaveCount(1); + messages.Should().HaveCount(1); var content = messages[0].GetContentAs(); content.UserId.Should().Be(existingUserWithSameGroup2.Id); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.User.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.User.cs index 5ec47bb34a..006ba19764 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.User.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.User.cs @@ -17,8 +17,8 @@ public async Task Create_user_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - string newLoginName = _fakers.DomainUser.Generate().LoginName; - string newDisplayName = _fakers.DomainUser.Generate().DisplayName!; + string newLoginName = _fakers.DomainUser.GenerateOne().LoginName; + string newDisplayName = _fakers.DomainUser.GenerateOne().DisplayName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -46,9 +46,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("loginName").With(value => value.Should().Be(newLoginName)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("displayName").With(value => value.Should().Be(newDisplayName)); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("loginName").WhoseValue.Should().Be(newLoginName); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("displayName").WhoseValue.Should().Be(newDisplayName); hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] { @@ -57,12 +57,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => (typeof(DomainUser), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - Guid newUserId = Guid.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + Guid newUserId = Guid.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { List messages = await dbContext.OutboxMessages.OrderBy(message => message.Id).ToListAsync(); - messages.ShouldHaveCount(1); + messages.Should().HaveCount(1); var content = messages[0].GetContentAs(); content.UserId.Should().Be(newUserId); @@ -77,9 +77,9 @@ public async Task Create_user_in_group_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - string newLoginName = _fakers.DomainUser.Generate().LoginName; + string newLoginName = _fakers.DomainUser.GenerateOne().LoginName; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -119,9 +119,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("loginName").With(value => value.Should().Be(newLoginName)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("displayName").With(value => value.Should().BeNull()); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("loginName").WhoseValue.Should().Be(newLoginName); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("displayName").WhoseValue.Should().BeNull(); hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] { @@ -131,12 +131,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => (typeof(DomainUser), ResourceDefinitionExtensibilityPoints.OnWriteSucceededAsync) }, options => options.WithStrictOrdering()); - Guid newUserId = Guid.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + Guid newUserId = Guid.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { List messages = await dbContext.OutboxMessages.OrderBy(message => message.Id).ToListAsync(); - messages.ShouldHaveCount(2); + messages.Should().HaveCount(2); var content1 = messages[0].GetContentAs(); content1.UserId.Should().Be(newUserId); @@ -155,10 +155,10 @@ public async Task Update_user_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); - string newLoginName = _fakers.DomainUser.Generate().LoginName; - string newDisplayName = _fakers.DomainUser.Generate().DisplayName!; + string newLoginName = _fakers.DomainUser.GenerateOne().LoginName; + string newDisplayName = _fakers.DomainUser.GenerateOne().DisplayName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -201,7 +201,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => await _testContext.RunOnDatabaseAsync(async dbContext => { List messages = await dbContext.OutboxMessages.OrderBy(message => message.Id).ToListAsync(); - messages.ShouldHaveCount(2); + messages.Should().HaveCount(2); var content1 = messages[0].GetContentAs(); content1.UserId.Should().Be(existingUser.Id); @@ -221,10 +221,10 @@ public async Task Update_user_clear_group_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - existingUser.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + existingUser.Group = _fakers.DomainGroup.GenerateOne(); - string newDisplayName = _fakers.DomainUser.Generate().DisplayName!; + string newDisplayName = _fakers.DomainUser.GenerateOne().DisplayName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -274,7 +274,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => await _testContext.RunOnDatabaseAsync(async dbContext => { List messages = await dbContext.OutboxMessages.OrderBy(message => message.Id).ToListAsync(); - messages.ShouldHaveCount(2); + messages.Should().HaveCount(2); var content1 = messages[0].GetContentAs(); content1.UserId.Should().Be(existingUser.Id); @@ -293,10 +293,10 @@ public async Task Update_user_add_to_group_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - string newDisplayName = _fakers.DomainUser.Generate().DisplayName!; + string newDisplayName = _fakers.DomainUser.GenerateOne().DisplayName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -350,7 +350,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => await _testContext.RunOnDatabaseAsync(async dbContext => { List messages = await dbContext.OutboxMessages.OrderBy(message => message.Id).ToListAsync(); - messages.ShouldHaveCount(2); + messages.Should().HaveCount(2); var content1 = messages[0].GetContentAs(); content1.UserId.Should().Be(existingUser.Id); @@ -369,12 +369,12 @@ public async Task Update_user_move_to_group_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - existingUser.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + existingUser.Group = _fakers.DomainGroup.GenerateOne(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - string newDisplayName = _fakers.DomainUser.Generate().DisplayName!; + string newDisplayName = _fakers.DomainUser.GenerateOne().DisplayName!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -428,7 +428,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => await _testContext.RunOnDatabaseAsync(async dbContext => { List messages = await dbContext.OutboxMessages.OrderBy(message => message.Id).ToListAsync(); - messages.ShouldHaveCount(2); + messages.Should().HaveCount(2); var content1 = messages[0].GetContentAs(); content1.UserId.Should().Be(existingUser.Id); @@ -448,7 +448,7 @@ public async Task Delete_user_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -476,7 +476,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => await _testContext.RunOnDatabaseAsync(async dbContext => { List messages = await dbContext.OutboxMessages.OrderBy(message => message.Id).ToListAsync(); - messages.ShouldHaveCount(1); + messages.Should().HaveCount(1); var content = messages[0].GetContentAs(); content.UserId.Should().Be(existingUser.Id); @@ -489,8 +489,8 @@ public async Task Delete_user_in_group_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - existingUser.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + existingUser.Group = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -518,7 +518,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => await _testContext.RunOnDatabaseAsync(async dbContext => { List messages = await dbContext.OutboxMessages.OrderBy(message => message.Id).ToListAsync(); - messages.ShouldHaveCount(2); + messages.Should().HaveCount(2); var content1 = messages[0].GetContentAs(); content1.UserId.Should().Be(existingUser.Id); @@ -535,8 +535,8 @@ public async Task Clear_group_from_user_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - existingUser.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + existingUser.Group = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -571,7 +571,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => await _testContext.RunOnDatabaseAsync(async dbContext => { List messages = await dbContext.OutboxMessages.OrderBy(message => message.Id).ToListAsync(); - messages.ShouldHaveCount(1); + messages.Should().HaveCount(1); var content = messages[0].GetContentAs(); content.UserId.Should().Be(existingUser.Id); @@ -585,8 +585,8 @@ public async Task Assign_group_to_user_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -625,7 +625,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => await _testContext.RunOnDatabaseAsync(async dbContext => { List messages = await dbContext.OutboxMessages.OrderBy(message => message.Id).ToListAsync(); - messages.ShouldHaveCount(1); + messages.Should().HaveCount(1); var content = messages[0].GetContentAs(); content.UserId.Should().Be(existingUser.Id); @@ -639,10 +639,10 @@ public async Task Replace_group_for_user_writes_to_outbox() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainUser existingUser = _fakers.DomainUser.Generate(); - existingUser.Group = _fakers.DomainGroup.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); + existingUser.Group = _fakers.DomainGroup.GenerateOne(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -681,7 +681,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => await _testContext.RunOnDatabaseAsync(async dbContext => { List messages = await dbContext.OutboxMessages.OrderBy(message => message.Id).ToListAsync(); - messages.ShouldHaveCount(1); + messages.Should().HaveCount(1); var content = messages[0].GetContentAs(); content.UserId.Should().Be(existingUser.Id); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.cs index 2faa69051a..7f4b1f072c 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Microservices/TransactionalOutboxPattern/OutboxTests.cs @@ -41,9 +41,9 @@ public async Task Does_not_add_to_outbox_on_write_error() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - DomainGroup existingGroup = _fakers.DomainGroup.Generate(); + DomainGroup existingGroup = _fakers.DomainGroup.GenerateOne(); - DomainUser existingUser = _fakers.DomainUser.Generate(); + DomainUser existingUser = _fakers.DomainUser.GenerateOne(); string unknownUserId = Unknown.StringId.For(); @@ -79,7 +79,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/MultiTenancyDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/MultiTenancyDbContext.cs index 2ace5fb3fd..d88be62da4 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/MultiTenancyDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/MultiTenancyDbContext.cs @@ -7,7 +7,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.MultiTenancy; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class MultiTenancyDbContext(DbContextOptions options, ITenantProvider tenantProvider) : TestableDbContext(options) +public sealed class MultiTenancyDbContext(DbContextOptions options, ITenantProvider tenantProvider) + : TestableDbContext(options) { private readonly ITenantProvider _tenantProvider = tenantProvider; diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/MultiTenancyTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/MultiTenancyTests.cs index e48470c6ab..cca888a7a1 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/MultiTenancyTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/MultiTenancyTests.cs @@ -43,7 +43,7 @@ public MultiTenancyTests(IntegrationTestContext shops = _fakers.WebShop.Generate(2); + List shops = _fakers.WebShop.GenerateList(2); shops[0].TenantId = OtherTenantId; shops[1].TenantId = ThisTenantId; @@ -62,7 +62,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(shops[1].StringId); } @@ -70,12 +70,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Filter_on_primary_resources_hides_other_tenants() { // Arrange - List shops = _fakers.WebShop.Generate(2); + List shops = _fakers.WebShop.GenerateList(2); shops[0].TenantId = OtherTenantId; - shops[0].Products = _fakers.WebProduct.Generate(1); + shops[0].Products = _fakers.WebProduct.GenerateList(1); shops[1].TenantId = ThisTenantId; - shops[1].Products = _fakers.WebProduct.Generate(1); + shops[1].Products = _fakers.WebProduct.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -92,7 +92,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(shops[1].StringId); } @@ -100,12 +100,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_primary_resources_with_include_hides_other_tenants() { // Arrange - List shops = _fakers.WebShop.Generate(2); + List shops = _fakers.WebShop.GenerateList(2); shops[0].TenantId = OtherTenantId; - shops[0].Products = _fakers.WebProduct.Generate(1); + shops[0].Products = _fakers.WebProduct.GenerateList(1); shops[1].TenantId = ThisTenantId; - shops[1].Products = _fakers.WebProduct.Generate(1); + shops[1].Products = _fakers.WebProduct.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -122,11 +122,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("webShops"); responseDocument.Data.ManyValue[0].Id.Should().Be(shops[1].StringId); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("webProducts"); responseDocument.Included[0].Id.Should().Be(shops[1].Products[0].StringId); } @@ -135,7 +135,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_primary_resource_by_ID_from_other_tenant() { // Arrange - WebShop shop = _fakers.WebShop.Generate(); + WebShop shop = _fakers.WebShop.GenerateOne(); shop.TenantId = OtherTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -152,7 +152,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -164,9 +164,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resources_from_other_parent_tenant() { // Arrange - WebShop shop = _fakers.WebShop.Generate(); + WebShop shop = _fakers.WebShop.GenerateOne(); shop.TenantId = OtherTenantId; - shop.Products = _fakers.WebProduct.Generate(1); + shop.Products = _fakers.WebProduct.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -182,7 +182,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -194,8 +194,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resource_from_other_parent_tenant() { // Arrange - WebProduct product = _fakers.WebProduct.Generate(); - product.Shop = _fakers.WebShop.Generate(); + WebProduct product = _fakers.WebProduct.GenerateOne(); + product.Shop = _fakers.WebShop.GenerateOne(); product.Shop.TenantId = OtherTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -212,7 +212,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -224,9 +224,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_ToMany_relationship_for_other_parent_tenant() { // Arrange - WebShop shop = _fakers.WebShop.Generate(); + WebShop shop = _fakers.WebShop.GenerateOne(); shop.TenantId = OtherTenantId; - shop.Products = _fakers.WebProduct.Generate(1); + shop.Products = _fakers.WebProduct.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -242,7 +242,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -254,8 +254,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_ToOne_relationship_for_other_parent_tenant() { // Arrange - WebProduct product = _fakers.WebProduct.Generate(); - product.Shop = _fakers.WebShop.Generate(); + WebProduct product = _fakers.WebProduct.GenerateOne(); + product.Shop = _fakers.WebShop.GenerateOne(); product.Shop.TenantId = OtherTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -272,7 +272,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -284,7 +284,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_resource() { // Arrange - string newShopUrl = _fakers.WebShop.Generate().Url; + string newShopUrl = _fakers.WebShop.GenerateOne().Url; var requestBody = new { @@ -306,11 +306,11 @@ public async Task Can_create_resource() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("url").With(value => value.Should().Be(newShopUrl)); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("url").WhoseValue.Should().Be(newShopUrl); + responseDocument.Data.SingleValue.Relationships.Should().NotBeNull(); - int newShopId = int.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + int newShopId = int.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -325,11 +325,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_resource_with_ToMany_relationship_to_other_tenant() { // Arrange - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = OtherTenantId; - string newShopUrl = _fakers.WebShop.Generate().Url; + string newShopUrl = _fakers.WebShop.GenerateOne().Url; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -371,7 +371,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -383,10 +383,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_resource_with_ToOne_relationship_to_other_tenant() { // Arrange - WebShop existingShop = _fakers.WebShop.Generate(); + WebShop existingShop = _fakers.WebShop.GenerateOne(); existingShop.TenantId = OtherTenantId; - string newProductName = _fakers.WebProduct.Generate().Name; + string newProductName = _fakers.WebProduct.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -425,7 +425,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -437,11 +437,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource() { // Arrange - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = ThisTenantId; - string newProductName = _fakers.WebProduct.Generate().Name; + string newProductName = _fakers.WebProduct.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -485,11 +485,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_from_other_tenant() { // Arrange - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = OtherTenantId; - string newProductName = _fakers.WebProduct.Generate().Name; + string newProductName = _fakers.WebProduct.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -518,7 +518,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -530,11 +530,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_ToMany_relationship_to_other_tenant() { // Arrange - WebShop existingShop = _fakers.WebShop.Generate(); + WebShop existingShop = _fakers.WebShop.GenerateOne(); existingShop.TenantId = ThisTenantId; - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = OtherTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -574,7 +574,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -586,11 +586,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_ToOne_relationship_to_other_tenant() { // Arrange - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = ThisTenantId; - WebShop existingShop = _fakers.WebShop.Generate(); + WebShop existingShop = _fakers.WebShop.GenerateOne(); existingShop.TenantId = OtherTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -627,7 +627,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -639,9 +639,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_ToMany_relationship_for_other_parent_tenant() { // Arrange - WebShop existingShop = _fakers.WebShop.Generate(); + WebShop existingShop = _fakers.WebShop.GenerateOne(); existingShop.TenantId = OtherTenantId; - existingShop.Products = _fakers.WebProduct.Generate(1); + existingShop.Products = _fakers.WebProduct.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -662,7 +662,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -674,11 +674,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_ToMany_relationship_to_other_tenant() { // Arrange - WebShop existingShop = _fakers.WebShop.Generate(); + WebShop existingShop = _fakers.WebShop.GenerateOne(); existingShop.TenantId = ThisTenantId; - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = OtherTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -707,7 +707,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -719,8 +719,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_ToOne_relationship_for_other_parent_tenant() { // Arrange - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = OtherTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -742,7 +742,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -754,11 +754,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_ToOne_relationship_to_other_tenant() { // Arrange - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = ThisTenantId; - WebShop existingShop = _fakers.WebShop.Generate(); + WebShop existingShop = _fakers.WebShop.GenerateOne(); existingShop.TenantId = OtherTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -784,7 +784,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -796,11 +796,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_to_ToMany_relationship_for_other_parent_tenant() { // Arrange - WebShop existingShop = _fakers.WebShop.Generate(); + WebShop existingShop = _fakers.WebShop.GenerateOne(); existingShop.TenantId = OtherTenantId; - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = ThisTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -829,7 +829,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -840,11 +840,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => [Fact] public async Task Cannot_add_to_ToMany_relationship_with_other_tenant() { - WebShop existingShop = _fakers.WebShop.Generate(); + WebShop existingShop = _fakers.WebShop.GenerateOne(); existingShop.TenantId = ThisTenantId; - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = OtherTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -873,7 +873,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -885,9 +885,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_from_ToMany_relationship_for_other_parent_tenant() { // Arrange - WebShop existingShop = _fakers.WebShop.Generate(); + WebShop existingShop = _fakers.WebShop.GenerateOne(); existingShop.TenantId = OtherTenantId; - existingShop.Products = _fakers.WebProduct.Generate(1); + existingShop.Products = _fakers.WebProduct.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -915,7 +915,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -927,8 +927,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource() { // Arrange - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = ThisTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -959,8 +959,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_delete_resource_from_other_tenant() { // Arrange - WebProduct existingProduct = _fakers.WebProduct.Generate(); - existingProduct.Shop = _fakers.WebShop.Generate(); + WebProduct existingProduct = _fakers.WebProduct.GenerateOne(); + existingProduct.Shop = _fakers.WebShop.GenerateOne(); existingProduct.Shop.TenantId = OtherTenantId; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -977,7 +977,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -989,9 +989,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Renders_links_with_tenant_route_parameter() { // Arrange - WebShop shop = _fakers.WebShop.Generate(); + WebShop shop = _fakers.WebShop.GenerateOne(); shop.TenantId = ThisTenantId; - shop.Products = _fakers.WebProduct.Generate(1); + shop.Products = _fakers.WebProduct.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1008,7 +1008,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be(route); responseDocument.Links.Related.Should().BeNull(); responseDocument.Links.First.Should().Be(responseDocument.Links.Self); @@ -1016,37 +1016,37 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Links.Prev.Should().BeNull(); responseDocument.Links.Next.Should().BeNull(); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].With(resource => { string shopLink = $"/nld/shops/{shop.StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(shopLink); - resource.Relationships.ShouldContainKey("products").With(value => + resource.Relationships.Should().ContainKey("products").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{shopLink}/relationships/products"); value.Links.Related.Should().Be($"{shopLink}/products"); }); }); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].With(resource => { string productLink = $"/nld/products/{shop.Products[0].StringId}"; - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be(productLink); - resource.Relationships.ShouldContainKey("shop").With(value => + resource.Relationships.Should().ContainKey("shop").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{productLink}/relationships/shop"); value.Links.Related.Should().Be($"{productLink}/shop"); }); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/KebabCasingConventionStartup.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/KebabCasingConventionStartup.cs index da3d3b10f9..6321943718 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/KebabCasingConventionStartup.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/KebabCasingConventionStartup.cs @@ -1,3 +1,4 @@ +using System.Text.Json; using JetBrains.Annotations; using JsonApiDotNetCore.Configuration; using TestBuildingBlocks; @@ -16,7 +17,7 @@ protected override void SetJsonApiOptions(JsonApiOptions options) options.UseRelativeLinks = true; options.IncludeTotalResourceCount = true; - options.SerializerOptions.PropertyNamingPolicy = JsonKebabCaseNamingPolicy.Instance; - options.SerializerOptions.DictionaryKeyPolicy = JsonKebabCaseNamingPolicy.Instance; + options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.KebabCaseLower; + options.SerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.KebabCaseLower; } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/KebabCasingTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/KebabCasingTests.cs index f7d407696e..afa1bdfcd0 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/KebabCasingTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/KebabCasingTests.cs @@ -23,8 +23,8 @@ public KebabCasingTests(IntegrationTestContext pools = _fakers.SwimmingPool.Generate(2); - pools[1].DivingBoards = _fakers.DivingBoard.Generate(1); + List pools = _fakers.SwimmingPool.GenerateList(2); + pools[1].DivingBoards = _fakers.DivingBoard.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -41,20 +41,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); - responseDocument.Data.ManyValue.Should().OnlyContain(resourceObject => resourceObject.Type == "swimming-pools"); - responseDocument.Data.ManyValue.Should().OnlyContain(resourceObject => resourceObject.Attributes.ShouldContainKey("is-indoor") != null); - responseDocument.Data.ManyValue.Should().OnlyContain(resourceObject => resourceObject.Relationships.ShouldContainKey("water-slides") != null); - responseDocument.Data.ManyValue.Should().OnlyContain(resourceObject => resourceObject.Relationships.ShouldContainKey("diving-boards") != null); + responseDocument.Data.ManyValue.Should().HaveCount(2); + responseDocument.Data.ManyValue.Should().OnlyContain(resource => resource.Type == "swimming-pools"); + responseDocument.Data.ManyValue.Should().OnlyContain(resource => resource.Attributes.Should().ContainKey2("is-indoor").WhoseValue != null); + responseDocument.Data.ManyValue.Should().OnlyContain(resource => resource.Relationships.Should().ContainKey2("water-slides").WhoseValue != null); + responseDocument.Data.ManyValue.Should().OnlyContain(resource => resource.Relationships.Should().ContainKey2("diving-boards").WhoseValue != null); decimal height = pools[1].DivingBoards[0].HeightInMeters; + string link = $"/public-api/diving-boards/{pools[1].DivingBoards[0].StringId}"; - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("diving-boards"); responseDocument.Included[0].Id.Should().Be(pools[1].DivingBoards[0].StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("height-in-meters").With(value => value.As().Should().BeApproximately(height)); + responseDocument.Included[0].Attributes.Should().ContainKey("height-in-meters").WhoseValue.As().Should().BeApproximately(height); responseDocument.Included[0].Relationships.Should().BeNull(); - responseDocument.Included[0].Links.ShouldNotBeNull().Self.Should().Be($"/public-api/diving-boards/{pools[1].DivingBoards[0].StringId}"); + responseDocument.Included[0].Links.RefShould().NotBeNull().And.Subject.Self.Should().Be(link); responseDocument.Meta.Should().ContainTotal(2); } @@ -63,8 +64,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_secondary_resources_with_sparse_fieldset() { // Arrange - SwimmingPool pool = _fakers.SwimmingPool.Generate(); - pool.WaterSlides = _fakers.WaterSlide.Generate(2); + SwimmingPool pool = _fakers.SwimmingPool.GenerateOne(); + pool.WaterSlides = _fakers.WaterSlide.GenerateList(2); pool.WaterSlides[0].LengthInMeters = 1; pool.WaterSlides[1].LengthInMeters = 5; @@ -83,17 +84,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("water-slides"); responseDocument.Data.ManyValue[0].Id.Should().Be(pool.WaterSlides[1].StringId); - responseDocument.Data.ManyValue[0].Attributes.ShouldHaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().HaveCount(1); } [Fact] public async Task Can_create_resource() { // Arrange - SwimmingPool newPool = _fakers.SwimmingPool.Generate(); + SwimmingPool newPool = _fakers.SwimmingPool.GenerateOne(); var requestBody = new { @@ -115,25 +116,25 @@ public async Task Can_create_resource() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("swimming-pools"); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("is-indoor").With(value => value.Should().Be(newPool.IsIndoor)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("is-indoor").WhoseValue.Should().Be(newPool.IsIndoor); - int newPoolId = int.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + int newPoolId = int.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); string poolLink = $"{route}/{newPoolId}"; - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("water-slides").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("water-slides").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{poolLink}/relationships/water-slides"); value.Links.Related.Should().Be($"{poolLink}/water-slides"); }); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("diving-boards").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("diving-boards").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{poolLink}/relationships/diving-boards"); value.Links.Related.Should().Be($"{poolLink}/diving-boards"); }); @@ -160,19 +161,19 @@ public async Task Applies_casing_convention_on_error_stack_trace() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body."); - error.Meta.ShouldContainKey("stack-trace"); + error.Meta.Should().ContainKey("stack-trace"); } [Fact] public async Task Applies_casing_convention_on_source_pointer_from_ModelState() { // Arrange - DivingBoard existingBoard = _fakers.DivingBoard.Generate(); + DivingBoard existingBoard = _fakers.DivingBoard.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -201,13 +202,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Input validation failed."); error.Detail.Should().Be("The field HeightInMeters must be between 1 and 20."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/attributes/height-in-meters"); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/NamingDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/NamingDbContext.cs index a13c4a44ae..8ab8a7e703 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/NamingDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/NamingDbContext.cs @@ -5,7 +5,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.NamingConventions; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class NamingDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class NamingDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet SwimmingPools => Set(); public DbSet WaterSlides => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/PascalCasingTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/PascalCasingTests.cs index 9f71d9de16..9da9e4e520 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/PascalCasingTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/PascalCasingTests.cs @@ -1,5 +1,4 @@ using System.Net; -using System.Text.Json; using FluentAssertions; using JsonApiDotNetCore.Serialization.Objects; using TestBuildingBlocks; @@ -24,8 +23,8 @@ public PascalCasingTests(IntegrationTestContext pools = _fakers.SwimmingPool.Generate(2); - pools[1].DivingBoards = _fakers.DivingBoard.Generate(1); + List pools = _fakers.SwimmingPool.GenerateList(2); + pools[1].DivingBoards = _fakers.DivingBoard.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -42,34 +41,31 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); - responseDocument.Data.ManyValue.Should().OnlyContain(resourceObject => resourceObject.Type == "SwimmingPools"); - responseDocument.Data.ManyValue.Should().OnlyContain(resourceObject => resourceObject.Attributes.ShouldContainKey("IsIndoor") != null); - responseDocument.Data.ManyValue.Should().OnlyContain(resourceObject => resourceObject.Relationships.ShouldContainKey("WaterSlides") != null); - responseDocument.Data.ManyValue.Should().OnlyContain(resourceObject => resourceObject.Relationships.ShouldContainKey("DivingBoards") != null); + responseDocument.Data.ManyValue.Should().HaveCount(2); + responseDocument.Data.ManyValue.Should().OnlyContain(resource => resource.Type == "SwimmingPools"); + responseDocument.Data.ManyValue.Should().OnlyContain(resource => resource.Attributes.Should().ContainKey2("IsIndoor").WhoseValue != null); + responseDocument.Data.ManyValue.Should().OnlyContain(resource => resource.Relationships.Should().ContainKey2("WaterSlides").WhoseValue != null); + responseDocument.Data.ManyValue.Should().OnlyContain(resource => resource.Relationships.Should().ContainKey2("DivingBoards").WhoseValue != null); decimal height = pools[1].DivingBoards[0].HeightInMeters; + string link = $"/PublicApi/DivingBoards/{pools[1].DivingBoards[0].StringId}"; - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("DivingBoards"); responseDocument.Included[0].Id.Should().Be(pools[1].DivingBoards[0].StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("HeightInMeters").With(value => value.As().Should().BeApproximately(height)); + responseDocument.Included[0].Attributes.Should().ContainKey("HeightInMeters").WhoseValue.As().Should().BeApproximately(height); responseDocument.Included[0].Relationships.Should().BeNull(); - responseDocument.Included[0].Links.ShouldNotBeNull().Self.Should().Be($"/PublicApi/DivingBoards/{pools[1].DivingBoards[0].StringId}"); + responseDocument.Included[0].Links.RefShould().NotBeNull().And.Subject.Self.Should().Be(link); - responseDocument.Meta.ShouldContainKey("Total").With(value => - { - JsonElement element = value.Should().BeOfType().Subject; - element.GetInt32().Should().Be(2); - }); + responseDocument.Meta.Should().ContainTotal(2, "Total"); } [Fact] public async Task Can_filter_secondary_resources_with_sparse_fieldset() { // Arrange - SwimmingPool pool = _fakers.SwimmingPool.Generate(); - pool.WaterSlides = _fakers.WaterSlide.Generate(2); + SwimmingPool pool = _fakers.SwimmingPool.GenerateOne(); + pool.WaterSlides = _fakers.WaterSlide.GenerateList(2); pool.WaterSlides[0].LengthInMeters = 1; pool.WaterSlides[1].LengthInMeters = 5; @@ -87,17 +83,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("WaterSlides"); responseDocument.Data.ManyValue[0].Id.Should().Be(pool.WaterSlides[1].StringId); - responseDocument.Data.ManyValue[0].Attributes.ShouldHaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().HaveCount(1); } [Fact] public async Task Can_create_resource() { // Arrange - SwimmingPool newPool = _fakers.SwimmingPool.Generate(); + SwimmingPool newPool = _fakers.SwimmingPool.GenerateOne(); var requestBody = new { @@ -119,25 +115,25 @@ public async Task Can_create_resource() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("SwimmingPools"); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("IsIndoor").With(value => value.Should().Be(newPool.IsIndoor)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("IsIndoor").WhoseValue.Should().Be(newPool.IsIndoor); - int newPoolId = int.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + int newPoolId = int.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); string poolLink = $"{route}/{newPoolId}"; - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("WaterSlides").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("WaterSlides").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{poolLink}/relationships/WaterSlides"); value.Links.Related.Should().Be($"{poolLink}/WaterSlides"); }); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("DivingBoards").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("DivingBoards").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"{poolLink}/relationships/DivingBoards"); value.Links.Related.Should().Be($"{poolLink}/DivingBoards"); }); @@ -164,19 +160,19 @@ public async Task Applies_casing_convention_on_error_stack_trace() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body."); - error.Meta.ShouldContainKey("StackTrace"); + error.Meta.Should().ContainKey("StackTrace"); } [Fact] public async Task Applies_casing_convention_on_source_pointer_from_ModelState() { // Arrange - DivingBoard existingBoard = _fakers.DivingBoard.Generate(); + DivingBoard existingBoard = _fakers.DivingBoard.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -205,13 +201,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Input validation failed."); error.Detail.Should().Be("The field HeightInMeters must be between 1 and 20."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/attributes/HeightInMeters"); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/EmptyDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/EmptyDbContext.cs index 33fa56a0bb..0717b6e3ae 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/EmptyDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/EmptyDbContext.cs @@ -5,4 +5,5 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.NonJsonApiControllers; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class EmptyDbContext(DbContextOptions options) : TestableDbContext(options); +public sealed class EmptyDbContext(DbContextOptions options) + : TestableDbContext(options); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/KnownDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/KnownDbContext.cs index 23aae10cd3..4a884f0fb2 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/KnownDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/KnownDbContext.cs @@ -5,7 +5,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.NonJsonApiControllers; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class KnownDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class KnownDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet KnownResources => Set(); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/NonJsonApiController.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/NonJsonApiController.cs index 59a17ab95a..86e99d791c 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/NonJsonApiController.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/NonJsonApiController.cs @@ -15,7 +15,8 @@ public IActionResult Get() [HttpPost] public async Task PostAsync() { - string name = await new StreamReader(Request.Body).ReadToEndAsync(); + using var reader = new StreamReader(Request.Body, leaveOpen: true); + string name = await reader.ReadToEndAsync(); if (string.IsNullOrEmpty(name)) { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/NonJsonApiControllerTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/NonJsonApiControllerTests.cs index bd5029736b..7c0c50cfc6 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/NonJsonApiControllerTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/NonJsonApiControllerTests.cs @@ -31,7 +31,7 @@ public async Task Get_skips_middleware_and_formatters() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - httpResponse.Content.Headers.ContentType.ShouldNotBeNull(); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); httpResponse.Content.Headers.ContentType.ToString().Should().Be("application/json; charset=utf-8"); string responseText = await httpResponse.Content.ReadAsStringAsync(); @@ -60,7 +60,7 @@ public async Task Post_skips_middleware_and_formatters() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - httpResponse.Content.Headers.ContentType.ShouldNotBeNull(); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); httpResponse.Content.Headers.ContentType.ToString().Should().Be("text/plain; charset=utf-8"); string responseText = await httpResponse.Content.ReadAsStringAsync(); @@ -81,7 +81,7 @@ public async Task Post_skips_error_handler() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - httpResponse.Content.Headers.ContentType.ShouldNotBeNull(); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); httpResponse.Content.Headers.ContentType.ToString().Should().Be("text/plain; charset=utf-8"); string responseText = await httpResponse.Content.ReadAsStringAsync(); @@ -110,7 +110,7 @@ public async Task Put_skips_middleware_and_formatters() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - httpResponse.Content.Headers.ContentType.ShouldNotBeNull(); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); httpResponse.Content.Headers.ContentType.ToString().Should().Be("text/plain; charset=utf-8"); string responseText = await httpResponse.Content.ReadAsStringAsync(); @@ -131,7 +131,7 @@ public async Task Patch_skips_middleware_and_formatters() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - httpResponse.Content.Headers.ContentType.ShouldNotBeNull(); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); httpResponse.Content.Headers.ContentType.ToString().Should().Be("text/plain; charset=utf-8"); string responseText = await httpResponse.Content.ReadAsStringAsync(); @@ -152,7 +152,7 @@ public async Task Delete_skips_middleware_and_formatters() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - httpResponse.Content.Headers.ContentType.ShouldNotBeNull(); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); httpResponse.Content.Headers.ContentType.ToString().Should().Be("text/plain; charset=utf-8"); string responseText = await httpResponse.Content.ReadAsStringAsync(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseExpression.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseExpression.cs index bea7ccd2ba..7a4bfa0788 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseExpression.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseExpression.cs @@ -1,5 +1,4 @@ using System.Text; -using JsonApiDotNetCore; using JsonApiDotNetCore.Queries.Expressions; namespace JsonApiDotNetCoreTests.IntegrationTests.QueryStrings.CustomFunctions.IsUpperCase; @@ -27,7 +26,7 @@ internal sealed class IsUpperCaseExpression : FilterExpression public IsUpperCaseExpression(ResourceFieldChainExpression targetAttribute) { - ArgumentGuard.NotNull(targetAttribute); + ArgumentNullException.ThrowIfNull(targetAttribute); TargetAttribute = targetAttribute; } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseFilterParseTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseFilterParseTests.cs index ff0f8f6e09..05265f3e46 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseFilterParseTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseFilterParseTests.cs @@ -20,7 +20,8 @@ public sealed class IsUpperCaseFilterParseTests : BaseParseTests public IsUpperCaseFilterParseTests() { - var resourceFactory = new ResourceFactory(new ServiceContainer()); + using var serviceProvider = new ServiceContainer(); + var resourceFactory = new ResourceFactory(serviceProvider); var scopeParser = new QueryStringParameterScopeParser(); var valueParser = new IsUpperCaseFilterParser(resourceFactory); @@ -50,13 +51,13 @@ public void Reader_Read_Fails(string parameterName, string parameterValue, strin InvalidQueryStringParameterException exception = action.Should().ThrowExactly().And; exception.ParameterName.Should().Be(parameterName); - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); ErrorObject error = exception.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified filter is invalid."); error.Detail.Should().Be($"{errorMessage} {parameterValueSource}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be(parameterName); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseFilterParser.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseFilterParser.cs index 27b32d7189..99c5b30bc2 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseFilterParser.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseFilterParser.cs @@ -6,7 +6,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.QueryStrings.CustomFunctions.IsUpperCase; -internal sealed class IsUpperCaseFilterParser(IResourceFactory resourceFactory) : FilterParser(resourceFactory) +internal sealed class IsUpperCaseFilterParser(IResourceFactory resourceFactory) + : FilterParser(resourceFactory) { protected override FilterExpression ParseFilter() { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseFilterTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseFilterTests.cs index be3240fdef..fa991e7544 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseFilterTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseFilterTests.cs @@ -31,7 +31,7 @@ public IsUpperCaseFilterTests(IntegrationTestContext blogs = _fakers.Blog.Generate(2); + List blogs = _fakers.Blog.GenerateList(2); blogs[0].Title = blogs[0].Title.ToLowerInvariant(); blogs[1].Title = blogs[1].Title.ToUpperInvariant(); @@ -51,7 +51,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("blogs"); responseDocument.Data.ManyValue[0].Id.Should().Be(blogs[1].StringId); } @@ -60,8 +60,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_casing_in_compound_expression_at_secondary_endpoint() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(3); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(3); blog.Posts[0].Caption = blog.Posts[0].Caption.ToUpperInvariant(); blog.Posts[0].Url = blog.Posts[0].Url.ToUpperInvariant(); @@ -86,7 +86,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("blogPosts"); responseDocument.Data.ManyValue[0].Id.Should().Be(blog.Posts[1].StringId); } @@ -95,11 +95,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_casing_in_included_resources() { // Arrange - List blogs = _fakers.Blog.Generate(2); + List blogs = _fakers.Blog.GenerateList(2); blogs[0].Title = blogs[0].Title.ToLowerInvariant(); blogs[1].Title = blogs[1].Title.ToUpperInvariant(); - blogs[1].Posts = _fakers.BlogPost.Generate(2); + blogs[1].Posts = _fakers.BlogPost.GenerateList(2); blogs[1].Posts[0].Caption = blogs[1].Posts[0].Caption.ToLowerInvariant(); blogs[1].Posts[1].Caption = blogs[1].Posts[1].Caption.ToUpperInvariant(); @@ -118,11 +118,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("blogs"); responseDocument.Data.ManyValue[0].Id.Should().Be(blogs[1].StringId); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("blogPosts"); responseDocument.Included[0].Id.Should().Be(blogs[1].Posts[1].StringId); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseWhereClauseBuilder.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseWhereClauseBuilder.cs index 691a5aacde..4968392ee4 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseWhereClauseBuilder.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/IsUpperCase/IsUpperCaseWhereClauseBuilder.cs @@ -19,7 +19,7 @@ public override Expression DefaultVisit(QueryExpression expression, QueryClauseB return base.DefaultVisit(expression, context); } - private Expression VisitIsUpperCase(IsUpperCaseExpression expression, QueryClauseBuilderContext context) + private BinaryExpression VisitIsUpperCase(IsUpperCaseExpression expression, QueryClauseBuilderContext context) { Expression propertyAccess = Visit(expression.TargetAttribute, context); MethodCallExpression toUpperMethodCall = Expression.Call(propertyAccess, ToUpperMethod); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthExpression.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthExpression.cs index 727d3ec808..1fcf8b45dd 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthExpression.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthExpression.cs @@ -1,5 +1,4 @@ using System.Text; -using JsonApiDotNetCore; using JsonApiDotNetCore.Queries.Expressions; namespace JsonApiDotNetCoreTests.IntegrationTests.QueryStrings.CustomFunctions.StringLength; @@ -31,7 +30,7 @@ internal sealed class LengthExpression : FunctionExpression public LengthExpression(ResourceFieldChainExpression targetAttribute) { - ArgumentGuard.NotNull(targetAttribute); + ArgumentNullException.ThrowIfNull(targetAttribute); TargetAttribute = targetAttribute; } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthFilterParseTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthFilterParseTests.cs index e9f07521ac..92c104f5a4 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthFilterParseTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthFilterParseTests.cs @@ -20,7 +20,8 @@ public sealed class LengthFilterParseTests : BaseParseTests public LengthFilterParseTests() { - var resourceFactory = new ResourceFactory(new ServiceContainer()); + using var serviceProvider = new ServiceContainer(); + var resourceFactory = new ResourceFactory(serviceProvider); var scopeParser = new QueryStringParameterScopeParser(); var valueParser = new LengthFilterParser(resourceFactory); @@ -50,13 +51,13 @@ public void Reader_Read_Fails(string parameterName, string parameterValue, strin InvalidQueryStringParameterException exception = action.Should().ThrowExactly().And; exception.ParameterName.Should().Be(parameterName); - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); ErrorObject error = exception.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified filter is invalid."); error.Detail.Should().Be($"{errorMessage} {parameterValueSource}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be(parameterName); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthFilterParser.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthFilterParser.cs index f429224290..f787319373 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthFilterParser.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthFilterParser.cs @@ -6,7 +6,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.QueryStrings.CustomFunctions.StringLength; -internal sealed class LengthFilterParser(IResourceFactory resourceFactory) : FilterParser(resourceFactory) +internal sealed class LengthFilterParser(IResourceFactory resourceFactory) + : FilterParser(resourceFactory) { protected override bool IsFunction(string name) { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthFilterTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthFilterTests.cs index 5b6874f5b9..da5091eed5 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthFilterTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthFilterTests.cs @@ -31,7 +31,7 @@ public LengthFilterTests(IntegrationTestContext blogs = _fakers.Blog.Generate(2); + List blogs = _fakers.Blog.GenerateList(2); blogs[0].Title = "X"; blogs[1].Title = "XXX"; @@ -51,7 +51,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("blogs"); responseDocument.Data.ManyValue[0].Id.Should().Be(blogs[1].StringId); } @@ -60,8 +60,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_length_at_secondary_endpoint() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(3); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(3); blog.Posts[0].Caption = "XXX"; blog.Posts[0].Url = "YYY"; @@ -86,7 +86,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("blogPosts"); responseDocument.Data.ManyValue[0].Id.Should().Be(blog.Posts[1].StringId); } @@ -95,11 +95,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_length_in_included_resources() { // Arrange - List blogs = _fakers.Blog.Generate(2); + List blogs = _fakers.Blog.GenerateList(2); blogs[0].Title = "X"; blogs[1].Title = "XXX"; - blogs[1].Posts = _fakers.BlogPost.Generate(2); + blogs[1].Posts = _fakers.BlogPost.GenerateList(2); blogs[1].Posts[0].Caption = "Y"; blogs[1].Posts[1].Caption = "YYY"; @@ -118,11 +118,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("blogs"); responseDocument.Data.ManyValue[0].Id.Should().Be(blogs[1].StringId); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("blogPosts"); responseDocument.Included[0].Id.Should().Be(blogs[1].Posts[1].StringId); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthOrderClauseBuilder.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthOrderClauseBuilder.cs index 4ea6068173..bb530a37b8 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthOrderClauseBuilder.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthOrderClauseBuilder.cs @@ -19,7 +19,7 @@ public override Expression DefaultVisit(QueryExpression expression, QueryClauseB return base.DefaultVisit(expression, context); } - private Expression VisitLength(LengthExpression expression, QueryClauseBuilderContext context) + private MemberExpression VisitLength(LengthExpression expression, QueryClauseBuilderContext context) { Expression propertyAccess = Visit(expression.TargetAttribute, context); return Expression.Property(propertyAccess, LengthPropertyGetter); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthSortParseTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthSortParseTests.cs index e7e16196e4..9e55ecb901 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthSortParseTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthSortParseTests.cs @@ -47,13 +47,13 @@ public void Reader_Read_Fails(string parameterName, string parameterValue, strin InvalidQueryStringParameterException exception = action.Should().ThrowExactly().And; exception.ParameterName.Should().Be(parameterName); - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); ErrorObject error = exception.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified sort is invalid."); error.Detail.Should().Be($"{errorMessage} {parameterValueSource}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be(parameterName); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthSortTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthSortTests.cs index 340e571ecf..078d48029a 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthSortTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthSortTests.cs @@ -31,7 +31,7 @@ public LengthSortTests(IntegrationTestContext blogs = _fakers.Blog.Generate(2); + List blogs = _fakers.Blog.GenerateList(2); blogs[0].Title = "X"; blogs[1].Title = "XXX"; @@ -51,7 +51,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue[0].Type.Should().Be("blogs"); responseDocument.Data.ManyValue[0].Id.Should().Be(blogs[1].StringId); @@ -64,8 +64,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_on_length_at_secondary_endpoint() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(3); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(3); blog.Posts[0].Caption = "XXX"; blog.Posts[0].Url = "YYY"; @@ -90,7 +90,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(3); + responseDocument.Data.ManyValue.Should().HaveCount(3); responseDocument.Data.ManyValue[0].Type.Should().Be("blogPosts"); responseDocument.Data.ManyValue[0].Id.Should().Be(blog.Posts[2].StringId); @@ -106,11 +106,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_on_length_in_included_resources() { // Arrange - List blogs = _fakers.Blog.Generate(2); + List blogs = _fakers.Blog.GenerateList(2); blogs[0].Title = "XXX"; blogs[1].Title = "X"; - blogs[1].Posts = _fakers.BlogPost.Generate(2); + blogs[1].Posts = _fakers.BlogPost.GenerateList(2); blogs[1].Posts[0].Caption = "YYY"; blogs[1].Posts[1].Caption = "Y"; @@ -129,7 +129,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue[0].Type.Should().Be("blogs"); responseDocument.Data.ManyValue[0].Id.Should().Be(blogs[1].StringId); @@ -137,7 +137,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Data.ManyValue[1].Type.Should().Be("blogs"); responseDocument.Data.ManyValue[1].Id.Should().Be(blogs[0].StringId); - responseDocument.Included.ShouldHaveCount(2); + responseDocument.Included.Should().HaveCount(2); responseDocument.Included[0].Type.Should().Be("blogPosts"); responseDocument.Included[0].Id.Should().Be(blogs[1].Posts[1].StringId); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthWhereClauseBuilder.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthWhereClauseBuilder.cs index 6d553bdd41..282b3416b4 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthWhereClauseBuilder.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/StringLength/LengthWhereClauseBuilder.cs @@ -19,7 +19,7 @@ public override Expression DefaultVisit(QueryExpression expression, QueryClauseB return base.DefaultVisit(expression, context); } - private Expression VisitLength(LengthExpression expression, QueryClauseBuilderContext context) + private MemberExpression VisitLength(LengthExpression expression, QueryClauseBuilderContext context) { Expression propertyAccess = Visit(expression.TargetAttribute, context); return Expression.Property(propertyAccess, LengthPropertyGetter); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumExpression.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumExpression.cs index 7e137ad3d7..f353c1552b 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumExpression.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumExpression.cs @@ -1,5 +1,4 @@ using System.Text; -using JsonApiDotNetCore; using JsonApiDotNetCore.Queries.Expressions; namespace JsonApiDotNetCoreTests.IntegrationTests.QueryStrings.CustomFunctions.Sum; @@ -38,8 +37,8 @@ internal sealed class SumExpression : FunctionExpression public SumExpression(ResourceFieldChainExpression targetToManyRelationship, QueryExpression selector) { - ArgumentGuard.NotNull(targetToManyRelationship); - ArgumentGuard.NotNull(selector); + ArgumentNullException.ThrowIfNull(targetToManyRelationship); + ArgumentNullException.ThrowIfNull(selector); TargetToManyRelationship = targetToManyRelationship; Selector = selector; diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumFilterParseTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumFilterParseTests.cs index cc4c3fc7e9..853ac7ac4d 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumFilterParseTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumFilterParseTests.cs @@ -20,7 +20,8 @@ public sealed class SumFilterParseTests : BaseParseTests public SumFilterParseTests() { - var resourceFactory = new ResourceFactory(new ServiceContainer()); + using var serviceProvider = new ServiceContainer(); + var resourceFactory = new ResourceFactory(serviceProvider); var scopeParser = new QueryStringParameterScopeParser(); var valueParser = new SumFilterParser(resourceFactory); @@ -57,13 +58,13 @@ public void Reader_Read_Fails(string parameterName, string parameterValue, strin InvalidQueryStringParameterException exception = action.Should().ThrowExactly().And; exception.ParameterName.Should().Be(parameterName); - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); ErrorObject error = exception.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified filter is invalid."); error.Detail.Should().Be($"{errorMessage} {parameterValueSource}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be(parameterName); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumFilterParser.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumFilterParser.cs index 1db57b4fc0..11cb521a07 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumFilterParser.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumFilterParser.cs @@ -6,7 +6,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.QueryStrings.CustomFunctions.Sum; -internal sealed class SumFilterParser(IResourceFactory resourceFactory) : FilterParser(resourceFactory) +internal sealed class SumFilterParser(IResourceFactory resourceFactory) + : FilterParser(resourceFactory) { private static readonly FieldChainPattern SingleToManyRelationshipChain = FieldChainPattern.Parse("M"); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumFilterTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumFilterTests.cs index 6589120922..0f25661029 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumFilterTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumFilterTests.cs @@ -32,13 +32,13 @@ public SumFilterTests(IntegrationTestContext posts = _fakers.BlogPost.Generate(2); + List posts = _fakers.BlogPost.GenerateList(2); - posts[0].Comments = _fakers.Comment.Generate(2).ToHashSet(); + posts[0].Comments = _fakers.Comment.GenerateSet(2); posts[0].Comments.ElementAt(0).NumStars = 0; posts[0].Comments.ElementAt(1).NumStars = 1; - posts[1].Comments = _fakers.Comment.Generate(2).ToHashSet(); + posts[1].Comments = _fakers.Comment.GenerateSet(2); posts[1].Comments.ElementAt(0).NumStars = 2; posts[1].Comments.ElementAt(1).NumStars = 3; @@ -57,7 +57,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("blogPosts"); responseDocument.Data.ManyValue[0].Id.Should().Be(posts[1].StringId); } @@ -66,19 +66,19 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_sum_on_count_at_secondary_endpoint() { // Arrange - List posts = _fakers.BlogPost.Generate(2); + List posts = _fakers.BlogPost.GenerateList(2); - posts[0].Comments = _fakers.Comment.Generate(2).ToHashSet(); + posts[0].Comments = _fakers.Comment.GenerateSet(2); posts[0].Comments.ElementAt(0).NumStars = 1; posts[0].Comments.ElementAt(1).NumStars = 1; - posts[0].Contributors = _fakers.Woman.Generate(1).OfType().ToHashSet(); + posts[0].Contributors = _fakers.Woman.GenerateSet(1); - posts[1].Comments = _fakers.Comment.Generate(2).ToHashSet(); + posts[1].Comments = _fakers.Comment.GenerateSet(2); posts[1].Comments.ElementAt(0).NumStars = 2; posts[1].Comments.ElementAt(1).NumStars = 2; - posts[1].Contributors = _fakers.Man.Generate(2).OfType().ToHashSet(); - posts[1].Contributors.ElementAt(0).Children = _fakers.Woman.Generate(3).OfType().ToHashSet(); - posts[1].Contributors.ElementAt(1).Children = _fakers.Man.Generate(3).OfType().ToHashSet(); + posts[1].Contributors = _fakers.Man.GenerateSet(2); + posts[1].Contributors.ElementAt(0).Children = _fakers.Woman.GenerateSet(3); + posts[1].Contributors.ElementAt(1).Children = _fakers.Man.GenerateSet(3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -95,7 +95,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("blogPosts"); responseDocument.Data.ManyValue[0].Id.Should().Be(posts[1].StringId); } @@ -104,14 +104,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_sum_in_included_resources() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(2); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(2); - blog.Posts[0].Comments = _fakers.Comment.Generate(2).ToHashSet(); + blog.Posts[0].Comments = _fakers.Comment.GenerateSet(2); blog.Posts[0].Comments.ElementAt(0).NumStars = 1; blog.Posts[0].Comments.ElementAt(1).NumStars = 1; - blog.Posts[1].Comments = _fakers.Comment.Generate(2).ToHashSet(); + blog.Posts[1].Comments = _fakers.Comment.GenerateSet(2); blog.Posts[1].Comments.ElementAt(0).NumStars = 1; blog.Posts[1].Comments.ElementAt(1).NumStars = 2; @@ -130,11 +130,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("blogs"); responseDocument.Data.ManyValue[0].Id.Should().Be(blog.StringId); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("blogPosts"); responseDocument.Included[0].Id.Should().Be(blog.Posts[1].StringId); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumWhereClauseBuilder.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumWhereClauseBuilder.cs index b14150e793..55b9102ff4 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumWhereClauseBuilder.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/Sum/SumWhereClauseBuilder.cs @@ -18,7 +18,7 @@ public override Expression DefaultVisit(QueryExpression expression, QueryClauseB return base.DefaultVisit(expression, context); } - private Expression VisitSum(SumExpression expression, QueryClauseBuilderContext context) + private MethodCallExpression VisitSum(SumExpression expression, QueryClauseBuilderContext context) { Expression collectionPropertyAccess = Visit(expression.TargetToManyRelationship, context); @@ -39,7 +39,7 @@ private LambdaExpression GetSelectorLambda(QueryExpression expression, QueryClau return Expression.Lambda(body, context.LambdaScope.Parameter); } - private static Expression SumExtensionMethodCall(LambdaExpression selector, QueryClauseBuilderContext context) + private static MethodCallExpression SumExtensionMethodCall(LambdaExpression selector, QueryClauseBuilderContext context) { return Expression.Call(context.ExtensionType, "Sum", [context.LambdaScope.Parameter.Type], context.Source, selector); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/FilterRewritingResourceDefinition.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/FilterRewritingResourceDefinition.cs index 1a704d3883..e6578e5c0c 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/FilterRewritingResourceDefinition.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/FilterRewritingResourceDefinition.cs @@ -2,16 +2,15 @@ using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Queries.Expressions; using JsonApiDotNetCore.Resources; -using TestBuildingBlocks; namespace JsonApiDotNetCoreTests.IntegrationTests.QueryStrings.CustomFunctions.TimeOffset; [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] -public class FilterRewritingResourceDefinition(IResourceGraph resourceGraph, ISystemClock systemClock) +public class FilterRewritingResourceDefinition(IResourceGraph resourceGraph, TimeProvider timeProvider) : JsonApiResourceDefinition(resourceGraph) where TResource : class, IIdentifiable { - private readonly FilterTimeOffsetRewriter _rewriter = new(systemClock); + private readonly FilterTimeOffsetRewriter _rewriter = new(timeProvider); public override FilterExpression? OnApplyFilter(FilterExpression? existingFilter) { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/FilterTimeOffsetRewriter.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/FilterTimeOffsetRewriter.cs index 9f9c97c73a..97c975a059 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/FilterTimeOffsetRewriter.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/FilterTimeOffsetRewriter.cs @@ -1,9 +1,8 @@ using JsonApiDotNetCore.Queries.Expressions; -using TestBuildingBlocks; namespace JsonApiDotNetCoreTests.IntegrationTests.QueryStrings.CustomFunctions.TimeOffset; -internal sealed class FilterTimeOffsetRewriter(ISystemClock systemClock) : QueryExpressionRewriter +internal sealed class FilterTimeOffsetRewriter(TimeProvider timeProvider) : QueryExpressionRewriter { private static readonly Dictionary InverseComparisonOperatorTable = new() { @@ -14,21 +13,21 @@ internal sealed class FilterTimeOffsetRewriter(ISystemClock systemClock) : Query [ComparisonOperator.LessOrEqual] = ComparisonOperator.GreaterOrEqual }; - private readonly ISystemClock _systemClock = systemClock; + private readonly TimeProvider _timeProvider = timeProvider; public override QueryExpression? VisitComparison(ComparisonExpression expression, object? argument) { if (expression.Right is TimeOffsetExpression timeOffset) { - DateTime currentTime = _systemClock.UtcNow.UtcDateTime; + DateTime utcNow = _timeProvider.GetUtcNow().UtcDateTime; var offsetComparison = new ComparisonExpression(timeOffset.Value < TimeSpan.Zero ? InverseComparisonOperatorTable[expression.Operator] : expression.Operator, - expression.Left, new LiteralConstantExpression(currentTime + timeOffset.Value)); + expression.Left, new LiteralConstantExpression(utcNow + timeOffset.Value)); ComparisonExpression? timeComparison = expression.Operator is ComparisonOperator.LessThan or ComparisonOperator.LessOrEqual ? new ComparisonExpression(timeOffset.Value < TimeSpan.Zero ? ComparisonOperator.LessOrEqual : ComparisonOperator.GreaterOrEqual, - expression.Left, new LiteralConstantExpression(currentTime)) + expression.Left, new LiteralConstantExpression(utcNow)) : null; return timeComparison == null ? offsetComparison : new LogicalExpression(LogicalOperator.And, offsetComparison, timeComparison); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/TimeOffsetExpression.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/TimeOffsetExpression.cs index 110e91012c..8229276acd 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/TimeOffsetExpression.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/TimeOffsetExpression.cs @@ -1,5 +1,4 @@ using System.Text; -using JsonApiDotNetCore; using JsonApiDotNetCore.Queries.Expressions; namespace JsonApiDotNetCoreTests.IntegrationTests.QueryStrings.CustomFunctions.TimeOffset; @@ -34,16 +33,16 @@ internal sealed class TimeOffsetExpression : FunctionExpression public TimeOffsetExpression(LiteralConstantExpression timeSpanConstant) { - ArgumentGuard.NotNull(timeSpanConstant); + ArgumentNullException.ThrowIfNull(timeSpanConstant); - if (timeSpanConstant.TypedValue.GetType() != typeof(TimeSpan)) + if (timeSpanConstant.TypedValue is not TimeSpan timeSpan) { throw new ArgumentException($"Constant must contain a {nameof(TimeSpan)}.", nameof(timeSpanConstant)); } _timeSpanConstant = timeSpanConstant; - Value = (TimeSpan)timeSpanConstant.TypedValue; + Value = timeSpan; } public override TResult Accept(QueryExpressionVisitor visitor, TArgument argument) diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/TimeOffsetFilterParser.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/TimeOffsetFilterParser.cs index 3114e75b77..81d80f64b6 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/TimeOffsetFilterParser.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/TimeOffsetFilterParser.cs @@ -4,7 +4,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.QueryStrings.CustomFunctions.TimeOffset; -internal sealed class TimeOffsetFilterParser(IResourceFactory resourceFactory) : FilterParser(resourceFactory) +internal sealed class TimeOffsetFilterParser(IResourceFactory resourceFactory) + : FilterParser(resourceFactory) { protected override bool IsFunction(string name) { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/TimeOffsetTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/TimeOffsetTests.cs index 8b8062674c..329af80475 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/TimeOffsetTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/CustomFunctions/TimeOffset/TimeOffsetTests.cs @@ -1,6 +1,5 @@ using System.Net; using FluentAssertions; -using FluentAssertions.Extensions; using Humanizer; using JsonApiDotNetCore.Queries.Expressions; using JsonApiDotNetCore.Queries.Parsing; @@ -27,7 +26,6 @@ public TimeOffsetTests(IntegrationTestContext { services.AddTransient(); - services.AddSingleton(); services.AddScoped(typeof(IResourceDefinition<,>), typeof(FilterRewritingResourceDefinition<,>)); }); } @@ -46,16 +44,17 @@ public TimeOffsetTests(IntegrationTestContext(); - - List reminders = _fakers.Reminder.Generate(7); - reminders[0].RemindsAt = clock.UtcNow.Add(TimeSpan.FromMinutes(-15)).DateTime.AsUtc(); - reminders[1].RemindsAt = clock.UtcNow.Add(TimeSpan.FromMinutes(-10)).DateTime.AsUtc(); - reminders[2].RemindsAt = clock.UtcNow.Add(TimeSpan.FromMinutes(-5)).DateTime.AsUtc(); - reminders[3].RemindsAt = clock.UtcNow.Add(TimeSpan.FromMinutes(0)).DateTime.AsUtc(); - reminders[4].RemindsAt = clock.UtcNow.Add(TimeSpan.FromMinutes(5)).DateTime.AsUtc(); - reminders[5].RemindsAt = clock.UtcNow.Add(TimeSpan.FromMinutes(10)).DateTime.AsUtc(); - reminders[6].RemindsAt = clock.UtcNow.Add(TimeSpan.FromMinutes(15)).DateTime.AsUtc(); + var timeProvider = _testContext.Factory.Services.GetRequiredService(); + DateTimeOffset utcNow = timeProvider.GetUtcNow(); + + List reminders = _fakers.Reminder.GenerateList(7); + reminders[0].RemindsAt = utcNow.Add(TimeSpan.FromMinutes(-15)).UtcDateTime; + reminders[1].RemindsAt = utcNow.Add(TimeSpan.FromMinutes(-10)).UtcDateTime; + reminders[2].RemindsAt = utcNow.Add(TimeSpan.FromMinutes(-5)).UtcDateTime; + reminders[3].RemindsAt = utcNow.Add(TimeSpan.FromMinutes(0)).UtcDateTime; + reminders[4].RemindsAt = utcNow.Add(TimeSpan.FromMinutes(5)).UtcDateTime; + reminders[5].RemindsAt = utcNow.Add(TimeSpan.FromMinutes(10)).UtcDateTime; + reminders[6].RemindsAt = utcNow.Add(TimeSpan.FromMinutes(15)).UtcDateTime; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -73,7 +72,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); int[] matchingRowIndices = matchingRowsExpected.Split(',').Select(int.Parse).ToArray(); - responseDocument.Data.ManyValue.ShouldHaveCount(matchingRowIndices.Length); + responseDocument.Data.ManyValue.Should().HaveCount(matchingRowIndices.Length); foreach (int rowIndex in matchingRowIndices) { @@ -94,13 +93,13 @@ public async Task Cannot_filter_comparison_on_missing_relative_time() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified filter is invalid."); error.Detail.Should().Be($"Time offset between quotes expected. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("filter"); } @@ -117,13 +116,13 @@ public async Task Cannot_filter_comparison_on_invalid_relative_time() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified filter is invalid."); error.Detail.Should().Be($"Failed to convert '*' of type 'String' to type 'TimeSpan'. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("filter"); } @@ -140,13 +139,13 @@ public async Task Cannot_filter_comparison_on_relative_time_at_left_side() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified filter is invalid."); error.Detail.Should().Be($"The 'timeOffset' function can only be used at the right side of comparisons. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("filter"); } @@ -163,13 +162,13 @@ public async Task Cannot_filter_any_on_relative_time() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified filter is invalid."); error.Detail.Should().Be($"Value between quotes expected. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("filter"); } @@ -186,13 +185,13 @@ public async Task Cannot_filter_text_match_on_relative_time() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified filter is invalid."); error.Detail.Should().Be($"Attribute of type 'String' expected. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("filter"); } @@ -200,16 +199,17 @@ public async Task Cannot_filter_text_match_on_relative_time() public async Task Can_filter_comparison_on_relative_time_in_nested_expression() { // Arrange - var clock = _testContext.Factory.Services.GetRequiredService(); + var timeProvider = _testContext.Factory.Services.GetRequiredService(); + DateTimeOffset utcNow = timeProvider.GetUtcNow(); - Calendar calendar = _fakers.Calendar.Generate(); - calendar.Appointments = _fakers.Appointment.Generate(2).ToHashSet(); + Calendar calendar = _fakers.Calendar.GenerateOne(); + calendar.Appointments = _fakers.Appointment.GenerateSet(2); - calendar.Appointments.ElementAt(0).Reminders = _fakers.Reminder.Generate(1); - calendar.Appointments.ElementAt(0).Reminders[0].RemindsAt = clock.UtcNow.DateTime.AsUtc(); + calendar.Appointments.ElementAt(0).Reminders = _fakers.Reminder.GenerateList(1); + calendar.Appointments.ElementAt(0).Reminders[0].RemindsAt = utcNow.UtcDateTime; - calendar.Appointments.ElementAt(1).Reminders = _fakers.Reminder.Generate(1); - calendar.Appointments.ElementAt(1).Reminders[0].RemindsAt = clock.UtcNow.Add(TimeSpan.FromMinutes(30)).DateTime.AsUtc(); + calendar.Appointments.ElementAt(1).Reminders = _fakers.Reminder.GenerateList(1); + calendar.Appointments.ElementAt(1).Reminders[0].RemindsAt = utcNow.Add(TimeSpan.FromMinutes(30)).UtcDateTime; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -225,7 +225,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(calendar.Appointments.ElementAt(1).StringId); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterDataTypeTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterDataTypeTests.cs index 9bacb8097e..2022505e0d 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterDataTypeTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterDataTypeTests.cs @@ -71,8 +71,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey(attributeName).With(value => value.Should().Be(value)); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey(attributeName).WhoseValue.Should().Be(propertyValue); } [Fact] @@ -99,8 +99,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someDecimal").With(value => value.Should().Be(resource.SomeDecimal)); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someDecimal").WhoseValue.Should().Be(resource.SomeDecimal); } [Fact] @@ -127,8 +127,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someGuid").With(value => value.Should().Be(resource.SomeGuid)); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someGuid").WhoseValue.Should().Be(resource.SomeGuid); } [Fact] @@ -155,10 +155,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someDateTimeInLocalZone") - .With(value => value.Should().Be(resource.SomeDateTimeInLocalZone)); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someDateTimeInLocalZone").WhoseValue.Should().Be(resource.SomeDateTimeInLocalZone); } [Fact] @@ -185,10 +184,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someDateTimeInUtcZone") - .With(value => value.Should().Be(resource.SomeDateTimeInUtcZone)); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someDateTimeInUtcZone").WhoseValue.Should().Be(resource.SomeDateTimeInUtcZone); } [Fact] @@ -215,8 +213,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someDateTimeOffset").With(value => value.Should().Be(resource.SomeDateTimeOffset)); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someDateTimeOffset").WhoseValue.Should().Be(resource.SomeDateTimeOffset); } [Fact] @@ -243,8 +241,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someTimeSpan").With(value => value.Should().Be(resource.SomeTimeSpan)); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someTimeSpan").WhoseValue.Should().Be(resource.SomeTimeSpan); } [Fact] @@ -271,8 +269,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someDateOnly").With(value => value.Should().Be(resource.SomeDateOnly)); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someDateOnly").WhoseValue.Should().Be(resource.SomeDateOnly); } [Fact] @@ -299,8 +297,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someTimeOnly").With(value => value.Should().Be(resource.SomeTimeOnly)); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someTimeOnly").WhoseValue.Should().Be(resource.SomeTimeOnly); } [Fact] @@ -328,13 +326,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified filter is invalid."); error.Detail.Should().Be($"Failed to convert 'ABC' of type 'String' to type 'Int32'. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("filter"); } @@ -392,8 +390,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey(attributeName).With(value => value.Should().BeNull()); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey(attributeName).WhoseValue.Should().BeNull(); } [Theory] @@ -446,7 +444,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey(attributeName).With(value => value.Should().NotBeNull()); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey(attributeName).WhoseValue.Should().NotBeNull(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterDbContext.cs index a3d6e5ec31..9b57bd9d50 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterDbContext.cs @@ -7,7 +7,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.QueryStrings.Filtering; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class FilterDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class FilterDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet FilterableResources => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterDepthTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterDepthTests.cs index 1bcf0563cf..cf8f696929 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterDepthTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterDepthTests.cs @@ -31,7 +31,7 @@ public FilterDepthTests(IntegrationTestContext posts = _fakers.BlogPost.Generate(2); + List posts = _fakers.BlogPost.GenerateList(2); posts[0].Caption = "One"; posts[1].Caption = "Two"; @@ -50,7 +50,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(posts[1].StringId); } @@ -58,7 +58,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_filter_in_primary_resource() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -74,13 +74,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified filter is invalid."); error.Detail.Should().Be($"{CollectionErrorMessage} Failed at position 1: ^filter"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("filter"); } @@ -88,8 +88,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_in_secondary_resources() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(2); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(2); blog.Posts[0].Caption = "One"; blog.Posts[1].Caption = "Two"; @@ -107,7 +107,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(blog.Posts[1].StringId); } @@ -115,7 +115,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_filter_in_secondary_resource() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -131,13 +131,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified filter is invalid."); error.Detail.Should().Be($"{CollectionErrorMessage} Failed at position 1: ^filter"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("filter"); } @@ -145,10 +145,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_on_ManyToOne_relationship() { // Arrange - List posts = _fakers.BlogPost.Generate(3); - posts[0].Author = _fakers.WebAccount.Generate(); + List posts = _fakers.BlogPost.GenerateList(3); + posts[0].Author = _fakers.WebAccount.GenerateOne(); posts[0].Author!.UserName = "Conner"; - posts[1].Author = _fakers.WebAccount.Generate(); + posts[1].Author = _fakers.WebAccount.GenerateOne(); posts[1].Author!.UserName = "Smith"; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -166,11 +166,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue.Should().ContainSingle(post => post.Id == posts[1].StringId); responseDocument.Data.ManyValue.Should().ContainSingle(post => post.Id == posts[2].StringId); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Id.Should().Be(posts[1].Author!.StringId); } @@ -178,8 +178,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_on_OneToMany_relationship() { // Arrange - List blogs = _fakers.Blog.Generate(2); - blogs[1].Posts = _fakers.BlogPost.Generate(1); + List blogs = _fakers.Blog.GenerateList(2); + blogs[1].Posts = _fakers.BlogPost.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -196,7 +196,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(blogs[1].StringId); } @@ -204,10 +204,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_on_OneToMany_relationship_with_nested_condition() { // Arrange - List blogs = _fakers.Blog.Generate(2); - blogs[0].Posts = _fakers.BlogPost.Generate(1); - blogs[1].Posts = _fakers.BlogPost.Generate(1); - blogs[1].Posts[0].Comments = _fakers.Comment.Generate(1).ToHashSet(); + List blogs = _fakers.Blog.GenerateList(2); + blogs[0].Posts = _fakers.BlogPost.GenerateList(1); + blogs[1].Posts = _fakers.BlogPost.GenerateList(1); + blogs[1].Posts[0].Comments = _fakers.Comment.GenerateSet(1); blogs[1].Posts[0].Comments.ElementAt(0).Text = "ABC"; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -225,7 +225,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(blogs[1].StringId); } @@ -233,8 +233,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_on_ManyToMany_relationship() { // Arrange - List posts = _fakers.BlogPost.Generate(2); - posts[1].Labels = _fakers.Label.Generate(1).ToHashSet(); + List posts = _fakers.BlogPost.GenerateList(2); + posts[1].Labels = _fakers.Label.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -251,7 +251,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(posts[1].StringId); } @@ -259,12 +259,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_on_ManyToMany_relationship_with_nested_condition() { // Arrange - List blogs = _fakers.Blog.Generate(2); + List blogs = _fakers.Blog.GenerateList(2); - blogs[0].Posts = _fakers.BlogPost.Generate(1); + blogs[0].Posts = _fakers.BlogPost.GenerateList(1); - blogs[1].Posts = _fakers.BlogPost.Generate(1); - blogs[1].Posts[0].Labels = _fakers.Label.Generate(1).ToHashSet(); + blogs[1].Posts = _fakers.BlogPost.GenerateList(1); + blogs[1].Posts[0].Labels = _fakers.Label.GenerateSet(1); blogs[1].Posts[0].Labels.ElementAt(0).Color = LabelColor.Green; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -282,7 +282,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(blogs[1].StringId); } @@ -290,8 +290,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_in_scope_of_OneToMany_relationship() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(2); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(2); blog.Posts[0].Caption = "One"; blog.Posts[1].Caption = "Two"; @@ -310,9 +310,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Id.Should().Be(blog.Posts[1].StringId); } @@ -320,9 +320,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_in_scope_of_OneToMany_relationship_at_secondary_endpoint() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Owner = _fakers.WebAccount.Generate(); - blog.Owner.Posts = _fakers.BlogPost.Generate(2); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Owner = _fakers.WebAccount.GenerateOne(); + blog.Owner.Posts = _fakers.BlogPost.GenerateList(2); blog.Owner.Posts[0].Caption = "One"; blog.Owner.Posts[1].Caption = "Two"; @@ -340,9 +340,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Id.Should().Be(blog.Owner.Posts[1].StringId); } @@ -350,12 +350,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_in_scope_of_ManyToMany_relationship() { // Arrange - List posts = _fakers.BlogPost.Generate(2); + List posts = _fakers.BlogPost.GenerateList(2); - posts[0].Labels = _fakers.Label.Generate(1).ToHashSet(); + posts[0].Labels = _fakers.Label.GenerateSet(1); posts[0].Labels.ElementAt(0).Name = "Cold"; - posts[1].Labels = _fakers.Label.Generate(1).ToHashSet(); + posts[1].Labels = _fakers.Label.GenerateSet(1); posts[1].Labels.ElementAt(0).Name = "Hot"; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -373,9 +373,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Id.Should().Be(posts[1].Labels.First().StringId); } @@ -383,9 +383,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_in_scope_of_relationship_chain() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Owner = _fakers.WebAccount.Generate(); - blog.Owner.Posts = _fakers.BlogPost.Generate(2); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Owner = _fakers.WebAccount.GenerateOne(); + blog.Owner.Posts = _fakers.BlogPost.GenerateList(2); blog.Owner.Posts[0].Caption = "One"; blog.Owner.Posts[1].Caption = "Two"; @@ -404,9 +404,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); - responseDocument.Included.ShouldHaveCount(2); + responseDocument.Included.Should().HaveCount(2); responseDocument.Included[0].Type.Should().Be("webAccounts"); responseDocument.Included[0].Id.Should().Be(blog.Owner.StringId); @@ -419,7 +419,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_in_same_scope_multiple_times() { // Arrange - List posts = _fakers.BlogPost.Generate(3); + List posts = _fakers.BlogPost.GenerateList(3); posts[0].Caption = "One"; posts[1].Caption = "Two"; posts[2].Caption = "Three"; @@ -439,7 +439,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue[0].Id.Should().Be(posts[0].StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(posts[2].StringId); } @@ -451,10 +451,10 @@ public async Task Can_filter_in_same_scope_multiple_times_using_legacy_notation( var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.EnableLegacyFilterNotation = true; - List posts = _fakers.BlogPost.Generate(3); - posts[0].Author = _fakers.WebAccount.Generate(); - posts[1].Author = _fakers.WebAccount.Generate(); - posts[2].Author = _fakers.WebAccount.Generate(); + List posts = _fakers.BlogPost.GenerateList(3); + posts[0].Author = _fakers.WebAccount.GenerateOne(); + posts[1].Author = _fakers.WebAccount.GenerateOne(); + posts[2].Author = _fakers.WebAccount.GenerateOne(); posts[0].Author!.UserName = "Joe"; posts[0].Author!.DisplayName = "Smith"; @@ -480,7 +480,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue[0].Id.Should().Be(posts[0].StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(posts[1].StringId); } @@ -489,14 +489,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_in_multiple_scopes() { // Arrange - List blogs = _fakers.Blog.Generate(2); + List blogs = _fakers.Blog.GenerateList(2); blogs[1].Title = "Technology"; - blogs[1].Owner = _fakers.WebAccount.Generate(); + blogs[1].Owner = _fakers.WebAccount.GenerateOne(); blogs[1].Owner!.UserName = "Smith"; - blogs[1].Owner!.Posts = _fakers.BlogPost.Generate(2); + blogs[1].Owner!.Posts = _fakers.BlogPost.GenerateList(2); blogs[1].Owner!.Posts[0].Caption = "One"; blogs[1].Owner!.Posts[1].Caption = "Two"; - blogs[1].Owner!.Posts[1].Comments = _fakers.Comment.Generate(2).ToHashSet(); + blogs[1].Owner!.Posts[1].Comments = _fakers.Comment.GenerateSet(2); blogs[1].Owner!.Posts[1].Comments.ElementAt(0).CreatedAt = 1.January(2000).AsUtc(); blogs[1].Owner!.Posts[1].Comments.ElementAt(1).CreatedAt = 10.January(2010).AsUtc(); @@ -522,10 +522,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(blogs[1].StringId); - responseDocument.Included.ShouldHaveCount(3); + responseDocument.Included.Should().HaveCount(3); responseDocument.Included[0].Type.Should().Be("webAccounts"); responseDocument.Included[0].Id.Should().Be(blogs[1].Owner!.StringId); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterOperatorTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterOperatorTests.cs index a955baa230..791c5ad18b 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterOperatorTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterOperatorTests.cs @@ -83,10 +83,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someString").With(value => value.Should().Be(resource.SomeString)); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someString").WhoseValue.Should().Be(resource.SomeString); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be("http://localhost/filterableResources?filter=equals(someString,'This%2c+that+%26+more+%2b+some')"); responseDocument.Links.First.Should().Be("http://localhost/filterableResources?filter=equals(someString,%27This,%20that%20%26%20more%20%2B%20some%27)"); } @@ -122,9 +122,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someInt32").With(value => value.Should().Be(resource.SomeInt32)); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("otherInt32").With(value => value.Should().Be(resource.OtherInt32)); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someInt32").WhoseValue.Should().Be(resource.SomeInt32); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("otherInt32").WhoseValue.Should().Be(resource.OtherInt32); } [Fact] @@ -158,9 +158,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someNullableInt32").With(value => value.Should().Be(resource.SomeNullableInt32)); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("otherNullableInt32").With(value => value.Should().Be(resource.OtherNullableInt32)); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someNullableInt32").WhoseValue.Should().Be(resource.SomeNullableInt32); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("otherNullableInt32").WhoseValue.Should().Be(resource.OtherNullableInt32); } [Fact] @@ -194,9 +194,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someInt32").With(value => value.Should().Be(resource.SomeInt32)); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someNullableInt32").With(value => value.Should().Be(resource.SomeNullableInt32)); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someInt32").WhoseValue.Should().Be(resource.SomeInt32); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someNullableInt32").WhoseValue.Should().Be(resource.SomeNullableInt32); } [Fact] @@ -230,9 +230,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someInt32").With(value => value.Should().Be(resource.SomeInt32)); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someNullableInt32").With(value => value.Should().Be(resource.SomeNullableInt32)); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someInt32").WhoseValue.Should().Be(resource.SomeInt32); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someNullableInt32").WhoseValue.Should().Be(resource.SomeNullableInt32); } [Fact] @@ -266,9 +266,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someInt32").With(value => value.Should().Be(resource.SomeInt32)); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someUnsignedInt64").With(value => value.Should().Be(resource.SomeUnsignedInt64)); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someInt32").WhoseValue.Should().Be(resource.SomeInt32); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someUnsignedInt64").WhoseValue.Should().Be(resource.SomeUnsignedInt64); } [Fact] @@ -283,7 +283,7 @@ public async Task Cannot_filter_equality_on_two_attributes_of_incompatible_types // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); @@ -330,8 +330,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someInt32").With(value => value.Should().Be(resource.SomeInt32)); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someInt32").WhoseValue.Should().Be(resource.SomeInt32); } [Theory] @@ -372,8 +372,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someDouble").With(value => value.Should().Be(resource.SomeDouble)); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someDouble").WhoseValue.Should().Be(resource.SomeDouble); } [Theory] @@ -422,10 +422,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someDateTimeInLocalZone") - .With(value => value.Should().Be(resource.SomeDateTimeInLocalZone)); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someDateTimeInLocalZone").WhoseValue.Should().Be(resource.SomeDateTimeInLocalZone); } [Theory] @@ -474,10 +473,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someDateTimeInUtcZone") - .With(value => value.Should().Be(resource.SomeDateTimeInUtcZone)); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someDateTimeInUtcZone").WhoseValue.Should().Be(resource.SomeDateTimeInUtcZone); } [Theory] @@ -526,9 +524,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someDateTimeOffset").With(value => value.Should().Be(resource.SomeDateTimeOffset)); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someDateTimeOffset").WhoseValue.Should().Be(resource.SomeDateTimeOffset); } [Theory] @@ -568,8 +566,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someTimeSpan").With(value => value.Should().Be(resource.SomeTimeSpan)); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someTimeSpan").WhoseValue.Should().Be(resource.SomeTimeSpan); } [Theory] @@ -617,8 +615,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someDateOnly").With(value => value.Should().Be(resource.SomeDateOnly)); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someDateOnly").WhoseValue.Should().Be(resource.SomeDateOnly); } [Theory] @@ -658,8 +656,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someTimeOnly").With(value => value.Should().Be(resource.SomeTimeOnly)); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someTimeOnly").WhoseValue.Should().Be(resource.SomeTimeOnly); } [Theory] @@ -696,8 +694,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someString").With(value => value.Should().Be(resource.SomeString)); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someString").WhoseValue.Should().Be(resource.SomeString); } [Fact] @@ -713,13 +711,13 @@ public async Task Cannot_filter_text_match_on_non_string_value() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified filter is invalid."); error.Detail.Should().Be($"Attribute of type 'String' expected. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("filter"); } @@ -736,13 +734,13 @@ public async Task Cannot_filter_text_match_on_nested_non_string_value() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified filter is invalid."); error.Detail.Should().Be($"Attribute of type 'String' expected. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("filter"); } @@ -778,8 +776,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("someString").With(value => value.Should().Be(resource.SomeString)); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("someString").WhoseValue.Should().Be(resource.SomeString); } [Fact] @@ -809,7 +807,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(resource.StringId); } @@ -817,8 +815,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_on_has_with_nested_condition() { // Arrange - var resources = new List - { + List resources = + [ new() { Children = new List @@ -839,7 +837,7 @@ public async Task Can_filter_on_has_with_nested_condition() } } } - }; + ]; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -856,7 +854,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(resources[1].StringId); } @@ -888,7 +886,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(resource.StringId); } @@ -925,7 +923,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(resource.Children.ElementAt(0).StringId); } @@ -942,13 +940,13 @@ public async Task Cannot_filter_on_count_with_incompatible_value() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified filter is invalid."); error.Detail.Should().Be($"Failed to convert 'ABC' of type 'String' to type 'Int32'. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("filter"); } @@ -989,7 +987,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(resource1.StringId); } @@ -1029,7 +1027,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(resource1.StringId); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterTests.cs index 42eca44c0b..2f6c468f08 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Filtering/FilterTests.cs @@ -37,13 +37,13 @@ public async Task Cannot_filter_in_unknown_scope() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified filter is invalid."); error.Detail.Should().Be($"Field '{Unknown.Relationship}' does not exist on resource type 'webAccounts'. {parameterName}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be(parameterName.Text); } @@ -60,13 +60,13 @@ public async Task Cannot_filter_in_unknown_nested_scope() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified filter is invalid."); error.Detail.Should().Be($"Field '{Unknown.Relationship}' does not exist on resource type 'blogPosts'. {parameterName}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be(parameterName.Text); } @@ -83,13 +83,13 @@ public async Task Cannot_filter_on_attribute_with_blocked_capability() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified filter is invalid."); error.Detail.Should().Be($"Filtering on attribute 'dateOfBirth' is not allowed. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("filter"); } @@ -106,13 +106,13 @@ public async Task Cannot_filter_on_ToMany_relationship_with_blocked_capability() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified filter is invalid."); error.Detail.Should().Be($"Filtering on relationship 'appointments' is not allowed. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("filter"); } @@ -120,7 +120,7 @@ public async Task Cannot_filter_on_ToMany_relationship_with_blocked_capability() public async Task Can_filter_on_ID() { // Arrange - List accounts = _fakers.WebAccount.Generate(2); + List accounts = _fakers.WebAccount.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -137,8 +137,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(accounts[0].StringId); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("userName").With(value => value.Should().Be(accounts[0].UserName)); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("userName").WhoseValue.Should().Be(accounts[0].UserName); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Includes/IncludeTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Includes/IncludeTests.cs index 3a5a67097d..3038ae9817 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Includes/IncludeTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Includes/IncludeTests.cs @@ -31,8 +31,8 @@ public IncludeTests(IntegrationTestContext public async Task Can_include_in_primary_resources() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); - post.Author = _fakers.WebAccount.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); + post.Author = _fakers.WebAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -49,22 +49,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(post.StringId); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("caption").With(value => value.Should().Be(post.Caption)); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(post.Caption); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("webAccounts"); responseDocument.Included[0].Id.Should().Be(post.Author.StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("displayName").With(value => value.Should().Be(post.Author.DisplayName)); + responseDocument.Included[0].Attributes.Should().ContainKey("displayName").WhoseValue.Should().Be(post.Author.DisplayName); } [Fact] public async Task Can_include_in_primary_resource_by_ID() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); - post.Author = _fakers.WebAccount.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); + post.Author = _fakers.WebAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -80,23 +80,23 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(post.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("caption").With(value => value.Should().Be(post.Caption)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(post.Caption); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("webAccounts"); responseDocument.Included[0].Id.Should().Be(post.Author.StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("displayName").With(value => value.Should().Be(post.Author.DisplayName)); + responseDocument.Included[0].Attributes.Should().ContainKey("displayName").WhoseValue.Should().Be(post.Author.DisplayName); } [Fact] public async Task Can_include_in_secondary_resource() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Owner = _fakers.WebAccount.Generate(); - blog.Owner.Posts = _fakers.BlogPost.Generate(1); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Owner = _fakers.WebAccount.GenerateOne(); + blog.Owner.Posts = _fakers.BlogPost.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -112,23 +112,23 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(blog.Owner.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("displayName").With(value => value.Should().Be(blog.Owner.DisplayName)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("displayName").WhoseValue.Should().Be(blog.Owner.DisplayName); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("blogPosts"); responseDocument.Included[0].Id.Should().Be(blog.Owner.Posts[0].StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("caption").With(value => value.Should().Be(blog.Owner.Posts[0].Caption)); + responseDocument.Included[0].Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(blog.Owner.Posts[0].Caption); } [Fact] public async Task Can_include_in_secondary_resources() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(1); - blog.Posts[0].Author = _fakers.WebAccount.Generate(); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(1); + blog.Posts[0].Author = _fakers.WebAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -144,23 +144,23 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(blog.Posts[0].StringId); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("caption").With(value => value.Should().Be(blog.Posts[0].Caption)); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(blog.Posts[0].Caption); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("webAccounts"); responseDocument.Included[0].Id.Should().Be(blog.Posts[0].Author!.StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("displayName").With(value => value.Should().Be(blog.Posts[0].Author!.DisplayName)); + responseDocument.Included[0].Attributes.Should().ContainKey("displayName").WhoseValue.Should().Be(blog.Posts[0].Author!.DisplayName); } [Fact] public async Task Can_include_ToOne_relationships() { // Arrange - Comment comment = _fakers.Comment.Generate(); - comment.Author = _fakers.WebAccount.Generate(); - comment.Parent = _fakers.BlogPost.Generate(); + Comment comment = _fakers.Comment.GenerateOne(); + comment.Author = _fakers.WebAccount.GenerateOne(); + comment.Parent = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -176,27 +176,27 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(comment.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("text").With(value => value.Should().Be(comment.Text)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("text").WhoseValue.Should().Be(comment.Text); - responseDocument.Included.ShouldHaveCount(2); + responseDocument.Included.Should().HaveCount(2); responseDocument.Included[0].Type.Should().Be("webAccounts"); responseDocument.Included[0].Id.Should().Be(comment.Author.StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("userName").With(value => value.Should().Be(comment.Author.UserName)); + responseDocument.Included[0].Attributes.Should().ContainKey("userName").WhoseValue.Should().Be(comment.Author.UserName); responseDocument.Included[1].Type.Should().Be("blogPosts"); responseDocument.Included[1].Id.Should().Be(comment.Parent.StringId); - responseDocument.Included[1].Attributes.ShouldContainKey("caption").With(value => value.Should().Be(comment.Parent.Caption)); + responseDocument.Included[1].Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(comment.Parent.Caption); } [Fact] public async Task Can_include_OneToMany_relationship() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); - post.Comments = _fakers.Comment.Generate(1).ToHashSet(); + BlogPost post = _fakers.BlogPost.GenerateOne(); + post.Comments = _fakers.Comment.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -212,24 +212,24 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(post.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("caption").With(value => value.Should().Be(post.Caption)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(post.Caption); DateTime createdAt = post.Comments.Single().CreatedAt; - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("comments"); responseDocument.Included[0].Id.Should().Be(post.Comments.Single().StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("createdAt").With(value => value.Should().Be(createdAt)); + responseDocument.Included[0].Attributes.Should().ContainKey("createdAt").WhoseValue.Should().Be(createdAt); } [Fact] public async Task Can_include_ManyToMany_relationship() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); - post.Labels = _fakers.Label.Generate(1).ToHashSet(); + BlogPost post = _fakers.BlogPost.GenerateOne(); + post.Labels = _fakers.Label.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -245,22 +245,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(post.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("caption").With(value => value.Should().Be(post.Caption)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(post.Caption); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("labels"); responseDocument.Included[0].Id.Should().Be(post.Labels.Single().StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("name").With(value => value.Should().Be(post.Labels.Single().Name)); + responseDocument.Included[0].Attributes.Should().ContainKey("name").WhoseValue.Should().Be(post.Labels.Single().Name); } [Fact] public async Task Can_include_ManyToMany_relationship_at_secondary_endpoint() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); - post.Labels = _fakers.Label.Generate(1).ToHashSet(); + BlogPost post = _fakers.BlogPost.GenerateOne(); + post.Labels = _fakers.Label.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -276,25 +276,25 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("labels"); responseDocument.Data.ManyValue[0].Id.Should().Be(post.Labels.ElementAt(0).StringId); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("name").With(value => value.Should().Be(post.Labels.Single().Name)); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("name").WhoseValue.Should().Be(post.Labels.Single().Name); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("blogPosts"); responseDocument.Included[0].Id.Should().Be(post.StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("caption").With(value => value.Should().Be(post.Caption)); + responseDocument.Included[0].Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(post.Caption); } [Fact] public async Task Can_include_chain_of_ToOne_relationships() { // Arrange - Comment comment = _fakers.Comment.Generate(); - comment.Parent = _fakers.BlogPost.Generate(); - comment.Parent.Author = _fakers.WebAccount.Generate(); - comment.Parent.Author.Preferences = _fakers.AccountPreferences.Generate(); + Comment comment = _fakers.Comment.GenerateOne(); + comment.Parent = _fakers.BlogPost.GenerateOne(); + comment.Parent.Author = _fakers.WebAccount.GenerateOne(); + comment.Parent.Author.Preferences = _fakers.AccountPreferences.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -310,34 +310,34 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(comment.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("text").With(value => value.Should().Be(comment.Text)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("text").WhoseValue.Should().Be(comment.Text); - responseDocument.Included.ShouldHaveCount(3); + responseDocument.Included.Should().HaveCount(3); responseDocument.Included[0].Type.Should().Be("blogPosts"); responseDocument.Included[0].Id.Should().Be(comment.Parent.StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("caption").With(value => value.Should().Be(comment.Parent.Caption)); + responseDocument.Included[0].Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(comment.Parent.Caption); responseDocument.Included[1].Type.Should().Be("webAccounts"); responseDocument.Included[1].Id.Should().Be(comment.Parent.Author.StringId); - responseDocument.Included[1].Attributes.ShouldContainKey("displayName").With(value => value.Should().Be(comment.Parent.Author.DisplayName)); + responseDocument.Included[1].Attributes.Should().ContainKey("displayName").WhoseValue.Should().Be(comment.Parent.Author.DisplayName); bool useDarkTheme = comment.Parent.Author.Preferences.UseDarkTheme; responseDocument.Included[2].Type.Should().Be("accountPreferences"); responseDocument.Included[2].Id.Should().Be(comment.Parent.Author.Preferences.StringId); - responseDocument.Included[2].Attributes.ShouldContainKey("useDarkTheme").With(value => value.Should().Be(useDarkTheme)); + responseDocument.Included[2].Attributes.Should().ContainKey("useDarkTheme").WhoseValue.Should().Be(useDarkTheme); } [Fact] public async Task Can_include_chain_of_OneToMany_relationships() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(1); - blog.Posts[0].Comments = _fakers.Comment.Generate(1).ToHashSet(); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(1); + blog.Posts[0].Comments = _fakers.Comment.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -353,32 +353,32 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(blog.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("title").With(value => value.Should().Be(blog.Title)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(blog.Title); - responseDocument.Included.ShouldHaveCount(2); + responseDocument.Included.Should().HaveCount(2); responseDocument.Included[0].Type.Should().Be("blogPosts"); responseDocument.Included[0].Id.Should().Be(blog.Posts[0].StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("caption").With(value => value.Should().Be(blog.Posts[0].Caption)); + responseDocument.Included[0].Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(blog.Posts[0].Caption); DateTime createdAt = blog.Posts[0].Comments.Single().CreatedAt; responseDocument.Included[1].Type.Should().Be("comments"); responseDocument.Included[1].Id.Should().Be(blog.Posts[0].Comments.Single().StringId); - responseDocument.Included[1].Attributes.ShouldContainKey("createdAt").With(value => value.Should().Be(createdAt)); + responseDocument.Included[1].Attributes.Should().ContainKey("createdAt").WhoseValue.Should().Be(createdAt); } [Fact] public async Task Can_include_chain_of_recursive_relationships() { // Arrange - Comment comment = _fakers.Comment.Generate(); - comment.Parent = _fakers.BlogPost.Generate(); - comment.Parent.Author = _fakers.WebAccount.Generate(); - comment.Parent.Comments = _fakers.Comment.Generate(2).ToHashSet(); - comment.Parent.Comments.ElementAt(0).Author = _fakers.WebAccount.Generate(); + Comment comment = _fakers.Comment.GenerateOne(); + comment.Parent = _fakers.BlogPost.GenerateOne(); + comment.Parent.Author = _fakers.WebAccount.GenerateOne(); + comment.Parent.Comments = _fakers.Comment.GenerateSet(2); + comment.Parent.Comments.ElementAt(0).Author = _fakers.WebAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -394,42 +394,42 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(comment.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("text").With(value => value.Should().Be(comment.Text)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("text").WhoseValue.Should().Be(comment.Text); - responseDocument.Included.ShouldHaveCount(4); + responseDocument.Included.Should().HaveCount(4); responseDocument.Included[0].Type.Should().Be("blogPosts"); responseDocument.Included[0].Id.Should().Be(comment.Parent.StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("caption").With(value => value.Should().Be(comment.Parent.Caption)); + responseDocument.Included[0].Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(comment.Parent.Caption); responseDocument.Included[1].Type.Should().Be("comments"); responseDocument.Included[1].Id.Should().Be(comment.Parent.Comments.ElementAt(0).StringId); - responseDocument.Included[1].Attributes.ShouldContainKey("text").With(value => value.Should().Be(comment.Parent.Comments.ElementAt(0).Text)); + responseDocument.Included[1].Attributes.Should().ContainKey("text").WhoseValue.Should().Be(comment.Parent.Comments.ElementAt(0).Text); string userName = comment.Parent.Comments.ElementAt(0).Author!.UserName; responseDocument.Included[2].Type.Should().Be("webAccounts"); responseDocument.Included[2].Id.Should().Be(comment.Parent.Comments.ElementAt(0).Author!.StringId); - responseDocument.Included[2].Attributes.ShouldContainKey("userName").With(value => value.Should().Be(userName)); + responseDocument.Included[2].Attributes.Should().ContainKey("userName").WhoseValue.Should().Be(userName); responseDocument.Included[3].Type.Should().Be("comments"); responseDocument.Included[3].Id.Should().Be(comment.Parent.Comments.ElementAt(1).StringId); - responseDocument.Included[3].Attributes.ShouldContainKey("text").With(value => value.Should().Be(comment.Parent.Comments.ElementAt(1).Text)); + responseDocument.Included[3].Attributes.Should().ContainKey("text").WhoseValue.Should().Be(comment.Parent.Comments.ElementAt(1).Text); } [Fact] public async Task Can_include_chain_of_relationships_with_multiple_paths() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(1); - blog.Posts[0].Author = _fakers.WebAccount.Generate(); - blog.Posts[0].Author!.Preferences = _fakers.AccountPreferences.Generate(); - blog.Posts[0].Comments = _fakers.Comment.Generate(2).ToHashSet(); - blog.Posts[0].Comments.ElementAt(0).Author = _fakers.WebAccount.Generate(); - blog.Posts[0].Comments.ElementAt(0).Author!.Posts = _fakers.BlogPost.Generate(1); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(1); + blog.Posts[0].Author = _fakers.WebAccount.GenerateOne(); + blog.Posts[0].Author!.Preferences = _fakers.AccountPreferences.GenerateOne(); + blog.Posts[0].Comments = _fakers.Comment.GenerateSet(2); + blog.Posts[0].Comments.ElementAt(0).Author = _fakers.WebAccount.GenerateOne(); + blog.Posts[0].Comments.ElementAt(0).Author!.Posts = _fakers.BlogPost.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -445,34 +445,34 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(blog.StringId); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("posts").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("posts").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.ManyValue.ShouldNotBeEmpty(); + value.Should().NotBeNull(); + value.Data.ManyValue.Should().NotBeEmpty(); value.Data.ManyValue[0].Type.Should().Be("blogPosts"); value.Data.ManyValue[0].Id.Should().Be(blog.Posts[0].StringId); }); - responseDocument.Included.ShouldHaveCount(7); + responseDocument.Included.Should().HaveCount(7); responseDocument.Included[0].Type.Should().Be("blogPosts"); responseDocument.Included[0].Id.Should().Be(blog.Posts[0].StringId); - responseDocument.Included[0].Relationships.ShouldContainKey("author").With(value => + responseDocument.Included[0].Relationships.Should().ContainKey("author").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.SingleValue.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Data.SingleValue.Should().NotBeNull(); value.Data.SingleValue.Type.Should().Be("webAccounts"); value.Data.SingleValue.Id.Should().Be(blog.Posts[0].Author!.StringId); }); - responseDocument.Included[0].Relationships.ShouldContainKey("comments").With(value => + responseDocument.Included[0].Relationships.Should().ContainKey("comments").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.ManyValue.ShouldNotBeEmpty(); + value.Should().NotBeNull(); + value.Data.ManyValue.Should().NotBeEmpty(); value.Data.ManyValue[0].Type.Should().Be("comments"); value.Data.ManyValue[0].Id.Should().Be(blog.Posts[0].Comments.ElementAt(0).StringId); }); @@ -480,17 +480,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Included[1].Type.Should().Be("webAccounts"); responseDocument.Included[1].Id.Should().Be(blog.Posts[0].Author!.StringId); - responseDocument.Included[1].Relationships.ShouldContainKey("preferences").With(value => + responseDocument.Included[1].Relationships.Should().ContainKey("preferences").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.SingleValue.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Data.SingleValue.Should().NotBeNull(); value.Data.SingleValue.Type.Should().Be("accountPreferences"); value.Data.SingleValue.Id.Should().Be(blog.Posts[0].Author!.Preferences!.StringId); }); - responseDocument.Included[1].Relationships.ShouldContainKey("posts").With(value => + responseDocument.Included[1].Relationships.Should().ContainKey("posts").WhoseValue.With(value => { - value.ShouldNotBeNull(); + value.Should().NotBeNull(); value.Data.Value.Should().BeNull(); }); @@ -500,10 +500,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Included[3].Type.Should().Be("comments"); responseDocument.Included[3].Id.Should().Be(blog.Posts[0].Comments.ElementAt(0).StringId); - responseDocument.Included[3].Relationships.ShouldContainKey("author").With(value => + responseDocument.Included[3].Relationships.Should().ContainKey("author").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.SingleValue.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Data.SingleValue.Should().NotBeNull(); value.Data.SingleValue.Type.Should().Be("webAccounts"); value.Data.SingleValue.Id.Should().Be(blog.Posts[0].Comments.ElementAt(0).Author!.StringId); }); @@ -511,41 +511,41 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Included[4].Type.Should().Be("webAccounts"); responseDocument.Included[4].Id.Should().Be(blog.Posts[0].Comments.ElementAt(0).Author!.StringId); - responseDocument.Included[4].Relationships.ShouldContainKey("posts").With(value => + responseDocument.Included[4].Relationships.Should().ContainKey("posts").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.ManyValue.ShouldNotBeEmpty(); + value.Should().NotBeNull(); + value.Data.ManyValue.Should().NotBeEmpty(); value.Data.ManyValue[0].Type.Should().Be("blogPosts"); value.Data.ManyValue[0].Id.Should().Be(blog.Posts[0].Comments.ElementAt(0).Author!.Posts[0].StringId); }); - responseDocument.Included[4].Relationships.ShouldContainKey("preferences").With(value => + responseDocument.Included[4].Relationships.Should().ContainKey("preferences").WhoseValue.With(value => { - value.ShouldNotBeNull(); + value.Should().NotBeNull(); value.Data.Value.Should().BeNull(); }); responseDocument.Included[5].Type.Should().Be("blogPosts"); responseDocument.Included[5].Id.Should().Be(blog.Posts[0].Comments.ElementAt(0).Author!.Posts[0].StringId); - responseDocument.Included[5].Relationships.ShouldContainKey("author").With(value => + responseDocument.Included[5].Relationships.Should().ContainKey("author").WhoseValue.With(value => { - value.ShouldNotBeNull(); + value.Should().NotBeNull(); value.Data.Value.Should().BeNull(); }); - responseDocument.Included[5].Relationships.ShouldContainKey("comments").With(value => + responseDocument.Included[5].Relationships.Should().ContainKey("comments").WhoseValue.With(value => { - value.ShouldNotBeNull(); + value.Should().NotBeNull(); value.Data.Value.Should().BeNull(); }); responseDocument.Included[6].Type.Should().Be("comments"); responseDocument.Included[6].Id.Should().Be(blog.Posts[0].Comments.ElementAt(1).StringId); - responseDocument.Included[5].Relationships.ShouldContainKey("author").With(value => + responseDocument.Included[5].Relationships.Should().ContainKey("author").WhoseValue.With(value => { - value.ShouldNotBeNull(); + value.Should().NotBeNull(); value.Data.Value.Should().BeNull(); }); } @@ -553,23 +553,23 @@ await _testContext.RunOnDatabaseAsync(async dbContext => [Fact] public async Task Can_include_chain_of_relationships_with_reused_resources() { - WebAccount author = _fakers.WebAccount.Generate(); - author.Preferences = _fakers.AccountPreferences.Generate(); - author.LoginAttempts = _fakers.LoginAttempt.Generate(1); + WebAccount author = _fakers.WebAccount.GenerateOne(); + author.Preferences = _fakers.AccountPreferences.GenerateOne(); + author.LoginAttempts = _fakers.LoginAttempt.GenerateList(1); - WebAccount reviewer = _fakers.WebAccount.Generate(); - reviewer.Preferences = _fakers.AccountPreferences.Generate(); - reviewer.LoginAttempts = _fakers.LoginAttempt.Generate(1); + WebAccount reviewer = _fakers.WebAccount.GenerateOne(); + reviewer.Preferences = _fakers.AccountPreferences.GenerateOne(); + reviewer.LoginAttempts = _fakers.LoginAttempt.GenerateList(1); - BlogPost post1 = _fakers.BlogPost.Generate(); + BlogPost post1 = _fakers.BlogPost.GenerateOne(); post1.Author = author; post1.Reviewer = reviewer; - WebAccount person = _fakers.WebAccount.Generate(); - person.Preferences = _fakers.AccountPreferences.Generate(); - person.LoginAttempts = _fakers.LoginAttempt.Generate(1); + WebAccount person = _fakers.WebAccount.GenerateOne(); + person.Preferences = _fakers.AccountPreferences.GenerateOne(); + person.LoginAttempts = _fakers.LoginAttempt.GenerateList(1); - BlogPost post2 = _fakers.BlogPost.Generate(); + BlogPost post2 = _fakers.BlogPost.GenerateOne(); post2.Author = person; post2.Reviewer = person; @@ -588,23 +588,23 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue[0].Type.Should().Be("blogPosts"); responseDocument.Data.ManyValue[0].Id.Should().Be(post1.StringId); - responseDocument.Data.ManyValue[0].Relationships.ShouldContainKey("author").With(value => + responseDocument.Data.ManyValue[0].Relationships.Should().ContainKey("author").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.SingleValue.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Data.SingleValue.Should().NotBeNull(); value.Data.SingleValue.Type.Should().Be("webAccounts"); value.Data.SingleValue.Id.Should().Be(author.StringId); }); - responseDocument.Data.ManyValue[0].Relationships.ShouldContainKey("reviewer").With(value => + responseDocument.Data.ManyValue[0].Relationships.Should().ContainKey("reviewer").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.SingleValue.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Data.SingleValue.Should().NotBeNull(); value.Data.SingleValue.Type.Should().Be("webAccounts"); value.Data.SingleValue.Id.Should().Be(reviewer.StringId); }); @@ -612,38 +612,38 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Data.ManyValue[1].Type.Should().Be("blogPosts"); responseDocument.Data.ManyValue[1].Id.Should().Be(post2.StringId); - responseDocument.Data.ManyValue[1].Relationships.ShouldContainKey("author").With(value => + responseDocument.Data.ManyValue[1].Relationships.Should().ContainKey("author").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.SingleValue.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Data.SingleValue.Should().NotBeNull(); value.Data.SingleValue.Type.Should().Be("webAccounts"); value.Data.SingleValue.Id.Should().Be(person.StringId); }); - responseDocument.Data.ManyValue[1].Relationships.ShouldContainKey("reviewer").With(value => + responseDocument.Data.ManyValue[1].Relationships.Should().ContainKey("reviewer").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.SingleValue.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Data.SingleValue.Should().NotBeNull(); value.Data.SingleValue.Type.Should().Be("webAccounts"); value.Data.SingleValue.Id.Should().Be(person.StringId); }); - responseDocument.Included.ShouldHaveCount(7); + responseDocument.Included.Should().HaveCount(7); responseDocument.Included[0].Type.Should().Be("webAccounts"); responseDocument.Included[0].Id.Should().Be(author.StringId); - responseDocument.Included[0].Relationships.ShouldContainKey("preferences").With(value => + responseDocument.Included[0].Relationships.Should().ContainKey("preferences").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.SingleValue.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Data.SingleValue.Should().NotBeNull(); value.Data.SingleValue.Type.Should().Be("accountPreferences"); value.Data.SingleValue.Id.Should().Be(author.Preferences.StringId); }); - responseDocument.Included[0].Relationships.ShouldContainKey("loginAttempts").With(value => + responseDocument.Included[0].Relationships.Should().ContainKey("loginAttempts").WhoseValue.With(value => { - value.ShouldNotBeNull(); + value.Should().NotBeNull(); value.Data.Value.Should().BeNull(); }); @@ -653,16 +653,16 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Included[2].Type.Should().Be("webAccounts"); responseDocument.Included[2].Id.Should().Be(reviewer.StringId); - responseDocument.Included[2].Relationships.ShouldContainKey("preferences").With(value => + responseDocument.Included[2].Relationships.Should().ContainKey("preferences").WhoseValue.With(value => { - value.ShouldNotBeNull(); + value.Should().NotBeNull(); value.Data.Value.Should().BeNull(); }); - responseDocument.Included[2].Relationships.ShouldContainKey("loginAttempts").With(value => + responseDocument.Included[2].Relationships.Should().ContainKey("loginAttempts").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.ManyValue.ShouldNotBeEmpty(); + value.Should().NotBeNull(); + value.Data.ManyValue.Should().NotBeEmpty(); value.Data.ManyValue[0].Type.Should().Be("loginAttempts"); value.Data.ManyValue[0].Id.Should().Be(reviewer.LoginAttempts[0].StringId); }); @@ -673,18 +673,18 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Included[4].Type.Should().Be("webAccounts"); responseDocument.Included[4].Id.Should().Be(person.StringId); - responseDocument.Included[4].Relationships.ShouldContainKey("preferences").With(value => + responseDocument.Included[4].Relationships.Should().ContainKey("preferences").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.SingleValue.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Data.SingleValue.Should().NotBeNull(); value.Data.SingleValue.Type.Should().Be("accountPreferences"); value.Data.SingleValue.Id.Should().Be(person.Preferences.StringId); }); - responseDocument.Included[4].Relationships.ShouldContainKey("loginAttempts").With(value => + responseDocument.Included[4].Relationships.Should().ContainKey("loginAttempts").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.ManyValue.ShouldNotBeEmpty(); + value.Should().NotBeNull(); + value.Data.ManyValue.Should().NotBeEmpty(); value.Data.ManyValue[0].Type.Should().Be("loginAttempts"); value.Data.ManyValue[0].Id.Should().Be(person.LoginAttempts[0].StringId); }); @@ -699,11 +699,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => [Fact] public async Task Can_include_chain_with_cyclic_dependency() { - List posts = _fakers.BlogPost.Generate(1); + List posts = _fakers.BlogPost.GenerateList(1); - Blog blog = _fakers.Blog.Generate(); + Blog blog = _fakers.Blog.GenerateOne(); blog.Posts = posts; - blog.Posts[0].Author = _fakers.WebAccount.Generate(); + blog.Posts[0].Author = _fakers.WebAccount.GenerateOne(); blog.Posts[0].Author!.Posts = posts; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -720,27 +720,27 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("blogs"); responseDocument.Data.SingleValue.Id.Should().Be(blog.StringId); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("posts").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("posts").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.ManyValue.ShouldNotBeEmpty(); + value.Should().NotBeNull(); + value.Data.ManyValue.Should().NotBeEmpty(); value.Data.ManyValue[0].Type.Should().Be("blogPosts"); value.Data.ManyValue[0].Id.Should().Be(blog.Posts[0].StringId); }); - responseDocument.Included.ShouldHaveCount(2); + responseDocument.Included.Should().HaveCount(2); responseDocument.Included[0].Type.Should().Be("blogPosts"); responseDocument.Included[0].Id.Should().Be(blog.Posts[0].StringId); - responseDocument.Included[0].Relationships.ShouldContainKey("author").With(value => + responseDocument.Included[0].Relationships.Should().ContainKey("author").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.SingleValue.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Data.SingleValue.Should().NotBeNull(); value.Data.SingleValue.Type.Should().Be("webAccounts"); value.Data.SingleValue.Id.Should().Be(blog.Posts[0].Author!.StringId); }); @@ -748,10 +748,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Included[1].Type.Should().Be("webAccounts"); responseDocument.Included[1].Id.Should().Be(blog.Posts[0].Author!.StringId); - responseDocument.Included[1].Relationships.ShouldContainKey("posts").With(value => + responseDocument.Included[1].Relationships.Should().ContainKey("posts").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.ManyValue.ShouldNotBeEmpty(); + value.Should().NotBeNull(); + value.Data.ManyValue.Should().NotBeEmpty(); value.Data.ManyValue[0].Type.Should().Be("blogPosts"); value.Data.ManyValue[0].Id.Should().Be(blog.Posts[0].StringId); }); @@ -761,9 +761,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Prevents_duplicate_includes_over_single_resource() { // Arrange - WebAccount account = _fakers.WebAccount.Generate(); + WebAccount account = _fakers.WebAccount.GenerateOne(); - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); post.Author = account; post.Reviewer = account; @@ -781,23 +781,23 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(post.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("caption").With(value => value.Should().Be(post.Caption)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(post.Caption); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("webAccounts"); responseDocument.Included[0].Id.Should().Be(account.StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("userName").With(value => value.Should().Be(account.UserName)); + responseDocument.Included[0].Attributes.Should().ContainKey("userName").WhoseValue.Should().Be(account.UserName); } [Fact] public async Task Prevents_duplicate_includes_over_multiple_resources() { // Arrange - WebAccount account = _fakers.WebAccount.Generate(); + WebAccount account = _fakers.WebAccount.GenerateOne(); - List posts = _fakers.BlogPost.Generate(2); + List posts = _fakers.BlogPost.GenerateList(2); posts[0].Author = account; posts[1].Author = account; @@ -816,19 +816,19 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("webAccounts"); responseDocument.Included[0].Id.Should().Be(account.StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("userName").With(value => value.Should().Be(account.UserName)); + responseDocument.Included[0].Attributes.Should().ContainKey("userName").WhoseValue.Should().Be(account.UserName); } [Fact] public async Task Can_select_empty_includes() { // Arrange - WebAccount account = _fakers.WebAccount.Generate(); + WebAccount account = _fakers.WebAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -844,7 +844,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Included.Should().BeEmpty(); } @@ -862,13 +862,13 @@ public async Task Cannot_include_unknown_relationship() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified include is invalid."); error.Detail.Should().Be($"Relationship '{Unknown.Relationship}' does not exist on resource type 'webAccounts'. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("include"); } @@ -885,13 +885,13 @@ public async Task Cannot_include_unknown_nested_relationship() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified include is invalid."); error.Detail.Should().Be($"Relationship '{Unknown.Relationship}' does not exist on resource type 'blogPosts'. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("include"); } @@ -908,13 +908,13 @@ public async Task Cannot_include_relationship_when_inclusion_blocked() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified include is invalid."); error.Detail.Should().Be($"Including the relationship 'parent' on 'blogPosts' is not allowed. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("include"); } @@ -931,13 +931,13 @@ public async Task Cannot_include_relationship_when_nested_inclusion_blocked() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified include is invalid."); error.Detail.Should().Be($"Including the relationship 'parent' on 'blogPosts' is not allowed. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("include"); } @@ -945,8 +945,8 @@ public async Task Cannot_include_relationship_when_nested_inclusion_blocked() public async Task Hides_relationship_and_related_resources_when_viewing_blocked() { // Arrange - Calendar calendar = _fakers.Calendar.Generate(); - calendar.Appointments = _fakers.Appointment.Generate(2).ToHashSet(); + Calendar calendar = _fakers.Calendar.GenerateOne(); + calendar.Appointments = _fakers.Appointment.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -962,11 +962,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("calendars"); responseDocument.Data.SingleValue.Id.Should().Be(calendar.StringId); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); responseDocument.Data.SingleValue.Relationships.Should().NotContainKey("appointments"); responseDocument.Included.Should().BeEmpty(); @@ -976,8 +976,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Hides_relationship_but_includes_related_resource_when_viewing_blocked_but_accessible_via_other_path() { // Arrange - Calendar calendar = _fakers.Calendar.Generate(); - calendar.MostRecentAppointment = _fakers.Appointment.Generate(); + Calendar calendar = _fakers.Calendar.GenerateOne(); + calendar.MostRecentAppointment = _fakers.Appointment.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -986,7 +986,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => calendar.Appointments = new[] { - _fakers.Appointment.Generate(), + _fakers.Appointment.GenerateOne(), calendar.MostRecentAppointment }.ToHashSet(); @@ -1001,21 +1001,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("calendars"); responseDocument.Data.SingleValue.Id.Should().Be(calendar.StringId); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("mostRecentAppointment").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("mostRecentAppointment").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.SingleValue.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Data.SingleValue.Should().NotBeNull(); value.Data.SingleValue.Type.Should().Be("appointments"); value.Data.SingleValue.Id.Should().Be(calendar.MostRecentAppointment.StringId); }); responseDocument.Data.SingleValue.Relationships.Should().NotContainKey("appointments"); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("appointments"); responseDocument.Included[0].Id.Should().Be(calendar.MostRecentAppointment.StringId); } @@ -1024,8 +1024,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Ignores_null_parent_in_nested_include() { // Arrange - List posts = _fakers.BlogPost.Generate(2); - posts[0].Reviewer = _fakers.WebAccount.Generate(); + List posts = _fakers.BlogPost.GenerateList(2); + posts[0].Reviewer = _fakers.WebAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1042,26 +1042,26 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); - responseDocument.Data.ManyValue.Should().OnlyContain(resource => resource.Relationships.ShouldContainKey("reviewer") != null); + responseDocument.Data.ManyValue.Should().OnlyContain(resource => resource.Relationships.Should().ContainKey2("reviewer").WhoseValue != null); ResourceObject[] postWithReviewer = responseDocument.Data.ManyValue .Where(resource => resource.Relationships!.First(pair => pair.Key == "reviewer").Value!.Data.SingleValue != null).ToArray(); - postWithReviewer.ShouldHaveCount(1); - postWithReviewer[0].Attributes.ShouldContainKey("caption").With(value => value.Should().Be(posts[0].Caption)); + postWithReviewer.Should().HaveCount(1); + postWithReviewer[0].Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(posts[0].Caption); ResourceObject[] postWithoutReviewer = responseDocument.Data.ManyValue .Where(resource => resource.Relationships!.First(pair => pair.Key == "reviewer").Value!.Data.SingleValue == null).ToArray(); - postWithoutReviewer.ShouldHaveCount(1); - postWithoutReviewer[0].Attributes.ShouldContainKey("caption").With(value => value.Should().Be(posts[1].Caption)); + postWithoutReviewer.Should().HaveCount(1); + postWithoutReviewer[0].Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(posts[1].Caption); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("webAccounts"); responseDocument.Included[0].Id.Should().Be(posts[0].Reviewer!.StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("userName").With(value => value.Should().Be(posts[0].Reviewer!.UserName)); + responseDocument.Included[0].Attributes.Should().ContainKey("userName").WhoseValue.Should().Be(posts[0].Reviewer!.UserName); } [Fact] @@ -1071,7 +1071,7 @@ public async Task Can_include_at_configured_maximum_inclusion_depth() var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.MaximumIncludeDepth = 1; - Blog blog = _fakers.Blog.Generate(); + Blog blog = _fakers.Blog.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1104,13 +1104,13 @@ public async Task Cannot_exceed_configured_maximum_inclusion_depth() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified include is invalid."); error.Detail.Should().Be($"Including 'posts.comments' exceeds the maximum inclusion depth of 1. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("include"); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/PaginationWithTotalCountTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/PaginationWithTotalCountTests.cs index ac1991ce4d..3fb7714c3f 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/PaginationWithTotalCountTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/PaginationWithTotalCountTests.cs @@ -37,7 +37,7 @@ public PaginationWithTotalCountTests(IntegrationTestContext posts = _fakers.BlogPost.Generate(2); + List posts = _fakers.BlogPost.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -54,10 +54,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(posts[1].StringId); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.First.Should().Be($"{HostPrefix}/blogPosts?page%5Bsize%5D=1"); responseDocument.Links.Last.Should().Be($"{HostPrefix}/blogPosts?page%5Bnumber%5D=2&page%5Bsize%5D=1"); @@ -69,7 +69,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_paginate_in_primary_resource() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -85,13 +85,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified pagination is invalid."); error.Detail.Should().Be($"{CollectionErrorMessage} Failed at position 1: ^page[number]"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("page[number]"); } @@ -99,11 +99,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_paginate_in_secondary_resources() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(5); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(5); - Blog otherBlog = _fakers.Blog.Generate(); - otherBlog.Posts = _fakers.BlogPost.Generate(1); + Blog otherBlog = _fakers.Blog.GenerateOne(); + otherBlog.Posts = _fakers.BlogPost.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -119,10 +119,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(blog.Posts[2].StringId); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.First.Should().Be($"{HostPrefix}/blogs/{blog.StringId}/posts?page%5Bsize%5D=1"); responseDocument.Links.Last.Should().Be($"{HostPrefix}/blogs/{blog.StringId}/posts?page%5Bnumber%5D=5&page%5Bsize%5D=1"); @@ -134,8 +134,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_paginate_in_secondary_resources_without_inverse_relationship() { // Arrange - WebAccount? account = _fakers.WebAccount.Generate(); - account.LoginAttempts = _fakers.LoginAttempt.Generate(2); + WebAccount account = _fakers.WebAccount.GenerateOne(); + account.LoginAttempts = _fakers.LoginAttempt.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -151,10 +151,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(account.LoginAttempts[1].StringId); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.First.Should().Be($"{HostPrefix}/webAccounts/{account.StringId}/loginAttempts?page%5Bsize%5D=1"); responseDocument.Links.Last.Should().BeNull(); @@ -166,7 +166,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_paginate_in_secondary_resource() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -182,13 +182,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified pagination is invalid."); error.Detail.Should().Be($"{CollectionErrorMessage} Failed at position 1: ^page[size]"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("page[size]"); } @@ -196,9 +196,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_paginate_in_scope_of_OneToMany_relationship() { // Arrange - List blogs = _fakers.Blog.Generate(3); - blogs[0].Posts = _fakers.BlogPost.Generate(2); - blogs[1].Posts = _fakers.BlogPost.Generate(2); + List blogs = _fakers.Blog.GenerateList(3); + blogs[0].Posts = _fakers.BlogPost.GenerateList(2); + blogs[1].Posts = _fakers.BlogPost.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -215,13 +215,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); - responseDocument.Included.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); + responseDocument.Included.Should().HaveCount(2); responseDocument.Included[0].Id.Should().Be(blogs[0].Posts[1].StringId); responseDocument.Included[1].Id.Should().Be(blogs[1].Posts[1].StringId); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.First.Should().Be($"{HostPrefix}/blogs?include=posts&page%5Bsize%5D=2,posts%3A1"); responseDocument.Links.Last.Should().Be($"{HostPrefix}/blogs?include=posts&page%5Bnumber%5D=2&page%5Bsize%5D=2,posts%3A1"); @@ -233,9 +233,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_paginate_in_scope_of_OneToMany_relationship_at_secondary_endpoint() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Owner = _fakers.WebAccount.Generate(); - blog.Owner.Posts = _fakers.BlogPost.Generate(2); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Owner = _fakers.WebAccount.GenerateOne(); + blog.Owner.Posts = _fakers.BlogPost.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -251,11 +251,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Id.Should().Be(blog.Owner.Posts[1].StringId); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.First.Should().BeNull(); responseDocument.Links.Last.Should().BeNull(); @@ -267,8 +267,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_paginate_OneToMany_relationship_at_relationship_endpoint() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(4); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(4); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -284,10 +284,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(blog.Posts[1].StringId); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.First.Should().Be($"{HostPrefix}/blogs/{blog.StringId}/relationships/posts?page%5Bsize%5D=1"); responseDocument.Links.Last.Should().Be($"{HostPrefix}/blogs/{blog.StringId}/relationships/posts?page%5Bnumber%5D=4&page%5Bsize%5D=1"); @@ -299,8 +299,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_paginate_OneToMany_relationship_at_relationship_endpoint_without_inverse_relationship() { // Arrange - WebAccount? account = _fakers.WebAccount.Generate(); - account.LoginAttempts = _fakers.LoginAttempt.Generate(2); + WebAccount account = _fakers.WebAccount.GenerateOne(); + account.LoginAttempts = _fakers.LoginAttempt.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -316,12 +316,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(account.LoginAttempts[1].StringId); string basePath = $"{HostPrefix}/webAccounts/{account.StringId}/relationships/loginAttempts"; - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.First.Should().Be($"{basePath}?page%5Bsize%5D=1"); responseDocument.Links.Last.Should().BeNull(); @@ -333,9 +333,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_paginate_in_scope_of_ManyToMany_relationship() { // Arrange - List posts = _fakers.BlogPost.Generate(2); - posts[0].Labels = _fakers.Label.Generate(2).ToHashSet(); - posts[1].Labels = _fakers.Label.Generate(2).ToHashSet(); + List posts = _fakers.BlogPost.GenerateList(2); + posts[0].Labels = _fakers.Label.GenerateSet(2); + posts[1].Labels = _fakers.Label.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -352,13 +352,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); - responseDocument.Included.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); + responseDocument.Included.Should().HaveCount(2); responseDocument.Included[0].Id.Should().Be(posts[0].Labels.ElementAt(1).StringId); responseDocument.Included[1].Id.Should().Be(posts[1].Labels.ElementAt(1).StringId); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.First.Should().Be($"{HostPrefix}/blogPosts?include=labels&page%5Bsize%5D=labels%3A1"); responseDocument.Links.Last.Should().Be(responseDocument.Links.First); @@ -370,8 +370,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_paginate_ManyToMany_relationship_at_relationship_endpoint() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); - post.Labels = _fakers.Label.Generate(4).ToHashSet(); + BlogPost post = _fakers.BlogPost.GenerateOne(); + post.Labels = _fakers.Label.GenerateSet(4); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -388,10 +388,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(post.Labels.ElementAt(1).StringId); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.First.Should().Be($"{HostPrefix}/blogPosts/{post.StringId}/relationships/labels?page%5Bsize%5D=1"); responseDocument.Links.Last.Should().Be($"{HostPrefix}/blogPosts/{post.StringId}/relationships/labels?page%5Bnumber%5D=4&page%5Bsize%5D=1"); @@ -403,10 +403,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_paginate_in_multiple_scopes() { // Arrange - List blogs = _fakers.Blog.Generate(2); - blogs[1].Owner = _fakers.WebAccount.Generate(); - blogs[1].Owner!.Posts = _fakers.BlogPost.Generate(2); - blogs[1].Owner!.Posts[1].Comments = _fakers.Comment.Generate(2).ToHashSet(); + List blogs = _fakers.Blog.GenerateList(2); + blogs[1].Owner = _fakers.WebAccount.GenerateOne(); + blogs[1].Owner!.Posts = _fakers.BlogPost.GenerateList(2); + blogs[1].Owner!.Posts[1].Comments = _fakers.Comment.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -424,10 +424,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(blogs[1].StringId); - responseDocument.Included.ShouldHaveCount(3); + responseDocument.Included.Should().HaveCount(3); responseDocument.Included[0].Type.Should().Be("webAccounts"); responseDocument.Included[0].Id.Should().Be(blogs[1].Owner!.StringId); @@ -440,7 +440,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => const string linkPrefix = $"{HostPrefix}/blogs?include=owner.posts.comments"; - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.First.Should().Be($"{linkPrefix}&page%5Bsize%5D=1,owner.posts%3A1,owner.posts.comments%3A1"); responseDocument.Links.Last.Should().Be($"{linkPrefix}&page%5Bsize%5D=1,owner.posts%3A1,owner.posts.comments%3A1&page%5Bnumber%5D=2"); @@ -461,13 +461,13 @@ public async Task Cannot_paginate_in_unknown_scope() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified pagination is invalid."); error.Detail.Should().Be($"Field '{Unknown.Relationship}' does not exist on resource type 'webAccounts'. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("page[number]"); } @@ -484,13 +484,13 @@ public async Task Cannot_paginate_in_unknown_nested_scope() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified pagination is invalid."); error.Detail.Should().Be($"Field '{Unknown.Relationship}' does not exist on resource type 'blogPosts'. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("page[size]"); } @@ -501,9 +501,9 @@ public async Task Uses_default_page_number_and_size() var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.DefaultPageSize = new PageSize(2); - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(3); - blog.Posts.ForEach(post => post.Labels = _fakers.Label.Generate(3).ToHashSet()); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(3); + blog.Posts.ForEach(post => post.Labels = _fakers.Label.GenerateSet(3)); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -519,13 +519,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue[0].Id.Should().Be(blog.Posts[0].StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(blog.Posts[1].StringId); - responseDocument.Included.ShouldHaveCount(4); + responseDocument.Included.Should().HaveCount(4); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.First.Should().Be(responseDocument.Links.Self); responseDocument.Links.Last.Should().Be($"{responseDocument.Links.Self}&page%5Bnumber%5D=2"); @@ -540,8 +540,8 @@ public async Task Returns_all_resources_when_pagination_is_disabled() var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.DefaultPageSize = null; - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(25); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(25); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -557,9 +557,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(25); + responseDocument.Data.ManyValue.Should().HaveCount(25); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.First.Should().BeNull(); responseDocument.Links.Last.Should().BeNull(); @@ -575,10 +575,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Renders_correct_top_level_links_for_page_number(int pageNumber, int? firstLink, int? lastLink, int? prevLink, int? nextLink) { // Arrange - WebAccount account = _fakers.WebAccount.Generate(); + WebAccount account = _fakers.WebAccount.GenerateOne(); const int totalCount = 3 * DefaultPageSize + 3; - List posts = _fakers.BlogPost.Generate(totalCount); + List posts = _fakers.BlogPost.GenerateList(totalCount); foreach (BlogPost post in posts) { @@ -592,9 +592,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => await dbContext.SaveChangesAsync(); }); - string routePrefix = $"/blogPosts?filter=equals(author.userName,'{account.UserName}')" + - "&fields[webAccounts]=userName&include=author&sort=id&foo=bar,baz"; - + string routePrefix = $"/blogPosts?filter=equals(author.userName,'{account.UserName}')&fields[webAccounts]=userName&include=author&sort=id&foo=bar,baz"; string route = $"{routePrefix}&page[number]={pageNumber}"; // Act @@ -603,8 +601,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.ShouldNotBeNull(); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Should().NotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); if (firstLink != null) diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/PaginationWithoutTotalCountTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/PaginationWithoutTotalCountTests.cs index 9af4e1201e..1bcfb0c6f5 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/PaginationWithoutTotalCountTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/PaginationWithoutTotalCountTests.cs @@ -44,7 +44,7 @@ public async Task Hides_pagination_links_when_unconstrained_page_size() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.First.Should().BeNull(); responseDocument.Links.Last.Should().BeNull(); @@ -73,7 +73,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.First.Should().Be($"{HostPrefix}/blogPosts?page%5Bsize%5D=8&foo=bar"); responseDocument.Links.Last.Should().BeNull(); @@ -99,7 +99,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.First.Should().Be($"{HostPrefix}/blogPosts?foo=bar"); responseDocument.Links.Last.Should().BeNull(); @@ -111,7 +111,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Renders_pagination_links_when_page_number_is_specified_in_query_string_with_partially_filled_page() { // Arrange - List posts = _fakers.BlogPost.Generate(12); + List posts = _fakers.BlogPost.GenerateList(12); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -130,7 +130,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Data.ManyValue.Should().HaveCountLessThan(DefaultPageSize); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.First.Should().Be($"{HostPrefix}/blogPosts?foo=bar"); responseDocument.Links.Last.Should().BeNull(); @@ -142,7 +142,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Renders_pagination_links_when_page_number_is_specified_in_query_string_with_full_page() { // Arrange - List posts = _fakers.BlogPost.Generate(DefaultPageSize * 3); + List posts = _fakers.BlogPost.GenerateList(DefaultPageSize * 3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -159,9 +159,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(DefaultPageSize); + responseDocument.Data.ManyValue.Should().HaveCount(DefaultPageSize); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.First.Should().Be($"{HostPrefix}/blogPosts?foo=bar"); responseDocument.Links.Last.Should().BeNull(); @@ -173,8 +173,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Renders_pagination_links_when_page_number_is_specified_in_query_string_with_full_page_at_secondary_endpoint() { // Arrange - WebAccount account = _fakers.WebAccount.Generate(); - account.Posts = _fakers.BlogPost.Generate(DefaultPageSize * 3); + WebAccount account = _fakers.WebAccount.GenerateOne(); + account.Posts = _fakers.BlogPost.GenerateList(DefaultPageSize * 3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -190,9 +190,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(DefaultPageSize); + responseDocument.Data.ManyValue.Should().HaveCount(DefaultPageSize); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be($"{HostPrefix}{route}"); responseDocument.Links.First.Should().Be($"{HostPrefix}/webAccounts/{account.StringId}/posts?foo=bar"); responseDocument.Links.Last.Should().BeNull(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/RangeValidationTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/RangeValidationTests.cs index 024e923313..687bffdc19 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/RangeValidationTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/RangeValidationTests.cs @@ -39,13 +39,13 @@ public async Task Cannot_use_negative_page_number() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified pagination is invalid."); error.Detail.Should().Be($"Page number cannot be negative or zero. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("page[number]"); } @@ -62,13 +62,13 @@ public async Task Cannot_use_zero_page_number() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified pagination is invalid."); error.Detail.Should().Be($"Page number cannot be negative or zero. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("page[number]"); } @@ -89,7 +89,7 @@ public async Task Can_use_positive_page_number() public async Task Returns_empty_set_of_resources_when_page_number_is_too_high() { // Arrange - List blogs = _fakers.Blog.Generate(3); + List blogs = _fakers.Blog.GenerateList(3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -122,13 +122,13 @@ public async Task Cannot_use_negative_page_size() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified pagination is invalid."); error.Detail.Should().Be($"Page size cannot be negative. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("page[size]"); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/RangeValidationWithMaximumTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/RangeValidationWithMaximumTests.cs index 5a8d375543..18141b6758 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/RangeValidationWithMaximumTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Pagination/RangeValidationWithMaximumTests.cs @@ -68,13 +68,13 @@ public async Task Cannot_use_page_number_over_maximum() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified pagination is invalid."); error.Detail.Should().Be($"Page number cannot be higher than {MaximumPageNumber}. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("page[number]"); } @@ -91,13 +91,13 @@ public async Task Cannot_use_zero_page_size() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified pagination is invalid."); error.Detail.Should().Be($"Page size cannot be unconstrained. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("page[size]"); } @@ -143,13 +143,13 @@ public async Task Cannot_use_page_size_over_maximum() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified pagination is invalid."); error.Detail.Should().Be($"Page size cannot be higher than {MaximumPageSize}. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("page[size]"); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/QueryStringDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/QueryStringDbContext.cs index 28a8935d26..0a7102c3d2 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/QueryStringDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/QueryStringDbContext.cs @@ -7,7 +7,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.QueryStrings; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class QueryStringDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class QueryStringDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet Blogs => Set(); public DbSet Posts => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/QueryStringTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/QueryStringTests.cs index 4f6ee95ad2..8bc14467cd 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/QueryStringTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/QueryStringTests.cs @@ -34,7 +34,7 @@ public async Task Cannot_use_unknown_query_string_parameter() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); @@ -43,7 +43,7 @@ public async Task Cannot_use_unknown_query_string_parameter() error.Detail.Should().Be("Query string parameter 'foo' is unknown. " + "Set 'AllowUnknownQueryStringParameters' to 'true' in options to ignore unknown parameters."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("foo"); } @@ -100,13 +100,13 @@ public async Task Cannot_use_empty_query_string_parameter_value(string parameter // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Missing query string parameter value."); error.Detail.Should().Be($"Missing value for '{parameterName}' query string parameter."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be(parameterName); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/SerializerIgnoreConditionTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/SerializerIgnoreConditionTests.cs index 0a6204cce4..7fa5aa7fcb 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/SerializerIgnoreConditionTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/SerializerIgnoreConditionTests.cs @@ -30,11 +30,11 @@ public async Task Applies_configuration_for_ignore_condition(JsonIgnoreCondition var options = (JsonApiOptions)Factory.Services.GetRequiredService(); options.SerializerOptions.DefaultIgnoreCondition = configurationValue; - Calendar calendar = _fakers.Calendar.Generate(); + Calendar calendar = _fakers.Calendar.GenerateOne(); calendar.TimeZone = null; - calendar.DefaultAppointmentDurationInMinutes = default; + calendar.DefaultAppointmentDurationInMinutes = 0; calendar.ShowWeekNumbers = true; - calendar.MostRecentAppointment = _fakers.Appointment.Generate(); + calendar.MostRecentAppointment = _fakers.Appointment.GenerateOne(); calendar.MostRecentAppointment.Description = null; calendar.MostRecentAppointment.StartTime = default; calendar.MostRecentAppointment.EndTime = 1.January(2001).AsUtc(); @@ -53,13 +53,13 @@ await RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Included.Should().HaveCount(1); if (expectNullValueInDocument) { - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("timeZone"); - responseDocument.Included[0].Attributes.ShouldContainKey("description"); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("timeZone"); + responseDocument.Included[0].Attributes.Should().ContainKey("description"); } else { @@ -69,8 +69,8 @@ await RunOnDatabaseAsync(async dbContext => if (expectDefaultValueInDocument) { - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("defaultAppointmentDurationInMinutes"); - responseDocument.Included[0].Attributes.ShouldContainKey("startTime"); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("defaultAppointmentDurationInMinutes"); + responseDocument.Included[0].Attributes.Should().ContainKey("startTime"); } else { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Sorting/SortTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Sorting/SortTests.cs index e1a1788105..45cd010379 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Sorting/SortTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Sorting/SortTests.cs @@ -27,7 +27,7 @@ public SortTests(IntegrationTestContext, Q public async Task Can_sort_in_primary_resources() { // Arrange - List posts = _fakers.BlogPost.Generate(3); + List posts = _fakers.BlogPost.GenerateList(3); posts[0].Caption = "B"; posts[1].Caption = "A"; posts[2].Caption = "C"; @@ -47,7 +47,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(3); + responseDocument.Data.ManyValue.Should().HaveCount(3); responseDocument.Data.ManyValue[0].Id.Should().Be(posts[1].StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(posts[0].StringId); responseDocument.Data.ManyValue[2].Id.Should().Be(posts[2].StringId); @@ -57,7 +57,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_sort_in_primary_resource() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -73,13 +73,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified sort is invalid."); error.Detail.Should().Be($"{CollectionErrorMessage} Failed at position 1: ^sort"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("sort"); } @@ -87,8 +87,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_in_secondary_resources() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(3); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(3); blog.Posts[0].Caption = "B"; blog.Posts[1].Caption = "A"; blog.Posts[2].Caption = "C"; @@ -107,7 +107,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(3); + responseDocument.Data.ManyValue.Should().HaveCount(3); responseDocument.Data.ManyValue[0].Id.Should().Be(blog.Posts[1].StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(blog.Posts[0].StringId); responseDocument.Data.ManyValue[2].Id.Should().Be(blog.Posts[2].StringId); @@ -117,7 +117,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_sort_in_secondary_resource() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -133,13 +133,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified sort is invalid."); error.Detail.Should().Be($"{CollectionErrorMessage} Failed at position 1: ^sort"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("sort"); } @@ -147,9 +147,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_on_OneToMany_relationship() { // Arrange - List blogs = _fakers.Blog.Generate(2); - blogs[0].Posts = _fakers.BlogPost.Generate(2); - blogs[1].Posts = _fakers.BlogPost.Generate(1); + List blogs = _fakers.Blog.GenerateList(2); + blogs[0].Posts = _fakers.BlogPost.GenerateList(2); + blogs[1].Posts = _fakers.BlogPost.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -166,7 +166,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue[0].Id.Should().Be(blogs[1].StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(blogs[0].StringId); } @@ -175,9 +175,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_on_ManyToMany_relationship() { // Arrange - List posts = _fakers.BlogPost.Generate(2); - posts[0].Labels = _fakers.Label.Generate(1).ToHashSet(); - posts[1].Labels = _fakers.Label.Generate(2).ToHashSet(); + List posts = _fakers.BlogPost.GenerateList(2); + posts[0].Labels = _fakers.Label.GenerateSet(1); + posts[1].Labels = _fakers.Label.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -194,7 +194,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue[0].Id.Should().Be(posts[1].StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(posts[0].StringId); } @@ -203,8 +203,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_in_scope_of_OneToMany_relationship() { // Arrange - WebAccount account = _fakers.WebAccount.Generate(); - account.Posts = _fakers.BlogPost.Generate(3); + WebAccount account = _fakers.WebAccount.GenerateOne(); + account.Posts = _fakers.BlogPost.GenerateList(3); account.Posts[0].Caption = "B"; account.Posts[1].Caption = "A"; account.Posts[2].Caption = "C"; @@ -223,10 +223,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(account.StringId); - responseDocument.Included.ShouldHaveCount(3); + responseDocument.Included.Should().HaveCount(3); responseDocument.Included[0].Id.Should().Be(account.Posts[1].StringId); responseDocument.Included[1].Id.Should().Be(account.Posts[0].StringId); responseDocument.Included[2].Id.Should().Be(account.Posts[2].StringId); @@ -236,9 +236,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_in_scope_of_OneToMany_relationship_at_secondary_endpoint() { // Arrange - Blog blog = _fakers.Blog.Generate(); - blog.Owner = _fakers.WebAccount.Generate(); - blog.Owner.Posts = _fakers.BlogPost.Generate(3); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Owner = _fakers.WebAccount.GenerateOne(); + blog.Owner.Posts = _fakers.BlogPost.GenerateList(3); blog.Owner.Posts[0].Caption = "B"; blog.Owner.Posts[1].Caption = "A"; blog.Owner.Posts[2].Caption = "C"; @@ -257,10 +257,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(blog.Owner.StringId); - responseDocument.Included.ShouldHaveCount(3); + responseDocument.Included.Should().HaveCount(3); responseDocument.Included[0].Id.Should().Be(blog.Owner.Posts[1].StringId); responseDocument.Included[1].Id.Should().Be(blog.Owner.Posts[0].StringId); responseDocument.Included[2].Id.Should().Be(blog.Owner.Posts[2].StringId); @@ -270,8 +270,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_in_scope_of_ManyToMany_relationship() { // Arrange - BlogPost post = _fakers.BlogPost.Generate(); - post.Labels = _fakers.Label.Generate(3).ToHashSet(); + BlogPost post = _fakers.BlogPost.GenerateOne(); + post.Labels = _fakers.Label.GenerateSet(3); post.Labels.ElementAt(0).Name = "B"; post.Labels.ElementAt(1).Name = "A"; post.Labels.ElementAt(2).Name = "C"; @@ -290,10 +290,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(post.StringId); - responseDocument.Included.ShouldHaveCount(3); + responseDocument.Included.Should().HaveCount(3); responseDocument.Included[0].Id.Should().Be(post.Labels.ElementAt(1).StringId); responseDocument.Included[1].Id.Should().Be(post.Labels.ElementAt(0).StringId); responseDocument.Included[2].Id.Should().Be(post.Labels.ElementAt(2).StringId); @@ -303,11 +303,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_on_multiple_fields_in_multiple_scopes() { // Arrange - List blogs = _fakers.Blog.Generate(2); + List blogs = _fakers.Blog.GenerateList(2); blogs[0].Title = "Z"; blogs[1].Title = "Y"; - blogs[0].Posts = _fakers.BlogPost.Generate(4); + blogs[0].Posts = _fakers.BlogPost.GenerateList(4); blogs[0].Posts[0].Caption = "B"; blogs[0].Posts[1].Caption = "A"; blogs[0].Posts[2].Caption = "A"; @@ -317,7 +317,7 @@ public async Task Can_sort_on_multiple_fields_in_multiple_scopes() blogs[0].Posts[2].Url = "www.some1.com"; blogs[0].Posts[3].Url = ""; - blogs[0].Posts[0].Comments = _fakers.Comment.Generate(3).ToHashSet(); + blogs[0].Posts[0].Comments = _fakers.Comment.GenerateSet(3); blogs[0].Posts[0].Comments.ElementAt(0).CreatedAt = 1.January(2015).AsUtc(); blogs[0].Posts[0].Comments.ElementAt(1).CreatedAt = 1.January(2014).AsUtc(); blogs[0].Posts[0].Comments.ElementAt(2).CreatedAt = 1.January(2016).AsUtc(); @@ -337,11 +337,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue[0].Id.Should().Be(blogs[1].StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(blogs[0].StringId); - responseDocument.Included.ShouldHaveCount(7); + responseDocument.Included.Should().HaveCount(7); responseDocument.Included[0].Type.Should().Be("blogPosts"); responseDocument.Included[0].Id.Should().Be(blogs[0].Posts[2].StringId); @@ -369,9 +369,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_on_ManyToOne_relationship() { // Arrange - List posts = _fakers.BlogPost.Generate(2); - posts[0].Author = _fakers.WebAccount.Generate(); - posts[1].Author = _fakers.WebAccount.Generate(); + List posts = _fakers.BlogPost.GenerateList(2); + posts[0].Author = _fakers.WebAccount.GenerateOne(); + posts[1].Author = _fakers.WebAccount.GenerateOne(); posts[0].Author!.DisplayName = "Conner"; posts[1].Author!.DisplayName = "Smith"; @@ -391,7 +391,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue[0].Id.Should().Be(posts[1].StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(posts[0].StringId); } @@ -400,16 +400,16 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_in_multiple_scopes() { // Arrange - List blogs = _fakers.Blog.Generate(2); + List blogs = _fakers.Blog.GenerateList(2); blogs[0].Title = "Cooking"; blogs[1].Title = "Technology"; - blogs[1].Owner = _fakers.WebAccount.Generate(); - blogs[1].Owner!.Posts = _fakers.BlogPost.Generate(2); + blogs[1].Owner = _fakers.WebAccount.GenerateOne(); + blogs[1].Owner!.Posts = _fakers.BlogPost.GenerateList(2); blogs[1].Owner!.Posts[0].Caption = "One"; blogs[1].Owner!.Posts[1].Caption = "Two"; - blogs[1].Owner!.Posts[1].Comments = _fakers.Comment.Generate(2).ToHashSet(); + blogs[1].Owner!.Posts[1].Comments = _fakers.Comment.GenerateSet(2); blogs[1].Owner!.Posts[1].Comments.ElementAt(0).CreatedAt = 1.January(2000).AsUtc(); blogs[1].Owner!.Posts[1].Comments.ElementAt(0).CreatedAt = 10.January(2010).AsUtc(); @@ -428,11 +428,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue[0].Id.Should().Be(blogs[1].StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(blogs[0].StringId); - responseDocument.Included.ShouldHaveCount(5); + responseDocument.Included.Should().HaveCount(5); responseDocument.Included[0].Type.Should().Be("webAccounts"); responseDocument.Included[0].Id.Should().Be(blogs[1].Owner!.StringId); @@ -463,13 +463,13 @@ public async Task Cannot_sort_in_unknown_scope() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified sort is invalid."); error.Detail.Should().Be($"Field '{Unknown.Relationship}' does not exist on resource type 'webAccounts'. {parameterName}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be(parameterName.Text); } @@ -486,13 +486,13 @@ public async Task Cannot_sort_in_unknown_nested_scope() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified sort is invalid."); error.Detail.Should().Be($"Field '{Unknown.Relationship}' does not exist on resource type 'blogPosts'. {parameterName}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be(parameterName.Text); } @@ -509,13 +509,13 @@ public async Task Cannot_sort_on_attribute_with_blocked_capability() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified sort is invalid."); error.Detail.Should().Be($"Sorting on attribute 'dateOfBirth' is not allowed. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("sort"); } @@ -523,7 +523,7 @@ public async Task Cannot_sort_on_attribute_with_blocked_capability() public async Task Can_sort_descending_by_ID() { // Arrange - List accounts = _fakers.WebAccount.Generate(3); + List accounts = _fakers.WebAccount.GenerateList(3); accounts[0].Id = 3000; accounts[1].Id = 2000; accounts[2].Id = 1000; @@ -547,7 +547,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(3); + responseDocument.Data.ManyValue.Should().HaveCount(3); responseDocument.Data.ManyValue[0].Id.Should().Be(accounts[1].StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(accounts[2].StringId); responseDocument.Data.ManyValue[2].Id.Should().Be(accounts[0].StringId); @@ -557,7 +557,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Sorts_by_ID_if_none_specified() { // Arrange - List accounts = _fakers.WebAccount.Generate(4); + List accounts = _fakers.WebAccount.GenerateList(4); accounts[0].Id = 300; accounts[1].Id = 200; accounts[2].Id = 100; @@ -578,7 +578,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(4); + responseDocument.Data.ManyValue.Should().HaveCount(4); responseDocument.Data.ManyValue[0].Id.Should().Be(accounts[2].StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(accounts[1].StringId); responseDocument.Data.ManyValue[2].Id.Should().Be(accounts[0].StringId); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/SparseFieldSets/ResultCapturingRepository.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/SparseFieldSets/ResultCapturingRepository.cs index 97eed95472..2e38517763 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/SparseFieldSets/ResultCapturingRepository.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/SparseFieldSets/ResultCapturingRepository.cs @@ -14,8 +14,9 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.QueryStrings.SparseFieldSets; public sealed class ResultCapturingRepository( ITargetedFields targetedFields, IDbContextResolver dbContextResolver, IResourceGraph resourceGraph, IResourceFactory resourceFactory, IEnumerable constraintProviders, ILoggerFactory loggerFactory, IResourceDefinitionAccessor resourceDefinitionAccessor, - ResourceCaptureStore captureStore) : EntityFrameworkCoreRepository(targetedFields, dbContextResolver, resourceGraph, resourceFactory, - constraintProviders, loggerFactory, resourceDefinitionAccessor) + ResourceCaptureStore captureStore) + : EntityFrameworkCoreRepository(targetedFields, dbContextResolver, resourceGraph, resourceFactory, constraintProviders, loggerFactory, + resourceDefinitionAccessor) where TResource : class, IIdentifiable { private readonly ResourceCaptureStore _captureStore = captureStore; diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/SparseFieldSets/SparseFieldSetTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/SparseFieldSets/SparseFieldSetTests.cs index feba8013b5..088c6cc7bf 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/SparseFieldSets/SparseFieldSetTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/SparseFieldSets/SparseFieldSetTests.cs @@ -39,7 +39,7 @@ public async Task Can_select_fields_in_primary_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -56,19 +56,19 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(post.StringId); - responseDocument.Data.ManyValue[0].Attributes.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("caption").With(value => value.Should().Be(post.Caption)); - responseDocument.Data.ManyValue[0].Relationships.ShouldHaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(post.Caption); + responseDocument.Data.ManyValue[0].Relationships.Should().HaveCount(1); - responseDocument.Data.ManyValue[0].Relationships.ShouldContainKey("author").With(value => + responseDocument.Data.ManyValue[0].Relationships.Should().ContainKey("author").WhoseValue.With(value => { - value.ShouldNotBeNull(); + value.Should().NotBeNull(); value.Data.Value.Should().BeNull(); - value.Links.ShouldNotBeNull(); - value.Links.Self.ShouldNotBeNull(); - value.Links.Related.ShouldNotBeNull(); + value.Links.Should().NotBeNull(); + value.Links.Self.Should().NotBeNull(); + value.Links.Related.Should().NotBeNull(); }); var postCaptured = (BlogPost)store.Resources.Should().ContainSingle(resource => resource is BlogPost).Which; @@ -83,7 +83,7 @@ public async Task Can_select_attribute_in_primary_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -100,10 +100,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(post.StringId); - responseDocument.Data.ManyValue[0].Attributes.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("caption").With(value => value.Should().Be(post.Caption)); + responseDocument.Data.ManyValue[0].Attributes.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(post.Caption); responseDocument.Data.ManyValue[0].Relationships.Should().BeNull(); var postCaptured = (BlogPost)store.Resources.Should().ContainSingle(resource => resource is BlogPost).Which; @@ -118,7 +118,7 @@ public async Task Can_select_relationship_in_primary_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -135,18 +135,18 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(post.StringId); responseDocument.Data.ManyValue[0].Attributes.Should().BeNull(); - responseDocument.Data.ManyValue[0].Relationships.ShouldHaveCount(1); + responseDocument.Data.ManyValue[0].Relationships.Should().HaveCount(1); - responseDocument.Data.ManyValue[0].Relationships.ShouldContainKey("author").With(value => + responseDocument.Data.ManyValue[0].Relationships.Should().ContainKey("author").WhoseValue.With(value => { - value.ShouldNotBeNull(); + value.Should().NotBeNull(); value.Data.Value.Should().BeNull(); - value.Links.ShouldNotBeNull(); - value.Links.Self.ShouldNotBeNull(); - value.Links.Related.ShouldNotBeNull(); + value.Links.Should().NotBeNull(); + value.Links.Self.Should().NotBeNull(); + value.Links.Related.Should().NotBeNull(); }); var postCaptured = (BlogPost)store.Resources.Should().ContainSingle(resource => resource is BlogPost).Which; @@ -161,8 +161,8 @@ public async Task Can_select_fields_in_secondary_resources() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Blog blog = _fakers.Blog.Generate(); - blog.Posts = _fakers.BlogPost.Generate(1); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Posts = _fakers.BlogPost.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -178,26 +178,26 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(blog.Posts[0].StringId); - responseDocument.Data.ManyValue[0].Attributes.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("caption").With(value => value.Should().Be(blog.Posts[0].Caption)); - responseDocument.Data.ManyValue[0].Relationships.ShouldHaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(blog.Posts[0].Caption); + responseDocument.Data.ManyValue[0].Relationships.Should().HaveCount(1); - responseDocument.Data.ManyValue[0].Relationships.ShouldContainKey("labels").With(value => + responseDocument.Data.ManyValue[0].Relationships.Should().ContainKey("labels").WhoseValue.With(value => { - value.ShouldNotBeNull(); + value.Should().NotBeNull(); value.Data.Value.Should().BeNull(); - value.Links.ShouldNotBeNull(); - value.Links.Self.ShouldNotBeNull(); - value.Links.Related.ShouldNotBeNull(); + value.Links.Should().NotBeNull(); + value.Links.Self.Should().NotBeNull(); + value.Links.Related.Should().NotBeNull(); }); var blogCaptured = (Blog)store.Resources.Should().ContainSingle(resource => resource is Blog).Which; blogCaptured.Id.Should().Be(blog.Id); blogCaptured.Title.Should().BeNull(); - blogCaptured.Posts.ShouldHaveCount(1); + blogCaptured.Posts.Should().HaveCount(1); blogCaptured.Posts[0].Caption.Should().Be(blog.Posts[0].Caption); blogCaptured.Posts[0].Url.Should().BeNull(); } @@ -209,7 +209,7 @@ public async Task Can_select_fields_in_primary_resource_by_ID() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -225,19 +225,19 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(post.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldHaveCount(1); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("url").With(value => value.Should().Be(post.Url)); - responseDocument.Data.SingleValue.Relationships.ShouldHaveCount(1); + responseDocument.Data.SingleValue.Attributes.Should().HaveCount(1); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("url").WhoseValue.Should().Be(post.Url); + responseDocument.Data.SingleValue.Relationships.Should().HaveCount(1); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("author").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("author").WhoseValue.With(value => { - value.ShouldNotBeNull(); + value.Should().NotBeNull(); value.Data.Value.Should().BeNull(); - value.Links.ShouldNotBeNull(); - value.Links.Self.ShouldNotBeNull(); - value.Links.Related.ShouldNotBeNull(); + value.Links.Should().NotBeNull(); + value.Links.Self.Should().NotBeNull(); + value.Links.Related.Should().NotBeNull(); }); var postCaptured = (BlogPost)store.Resources.Should().ContainSingle(resource => resource is BlogPost).Which; @@ -252,8 +252,8 @@ public async Task Can_select_fields_of_ManyToOne_relationship() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - BlogPost post = _fakers.BlogPost.Generate(); - post.Author = _fakers.WebAccount.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); + post.Author = _fakers.WebAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -269,41 +269,41 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(post.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("caption").With(value => value.Should().Be(post.Caption)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(post.Caption); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("author").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("author").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.SingleValue.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Data.SingleValue.Should().NotBeNull(); value.Data.SingleValue.Id.Should().Be(post.Author.StringId); - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); - value.Links.Self.ShouldNotBeNull(); - value.Links.Related.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); + value.Links.Self.Should().NotBeNull(); + value.Links.Related.Should().NotBeNull(); }); - responseDocument.Included.ShouldHaveCount(1); - responseDocument.Included[0].Attributes.ShouldHaveCount(2); - responseDocument.Included[0].Attributes.ShouldContainKey("displayName").With(value => value.Should().Be(post.Author.DisplayName)); - responseDocument.Included[0].Attributes.ShouldContainKey("emailAddress").With(value => value.Should().Be(post.Author.EmailAddress)); - responseDocument.Included[0].Relationships.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); + responseDocument.Included[0].Attributes.Should().HaveCount(2); + responseDocument.Included[0].Attributes.Should().ContainKey("displayName").WhoseValue.Should().Be(post.Author.DisplayName); + responseDocument.Included[0].Attributes.Should().ContainKey("emailAddress").WhoseValue.Should().Be(post.Author.EmailAddress); + responseDocument.Included[0].Relationships.Should().HaveCount(1); - responseDocument.Included[0].Relationships.ShouldContainKey("preferences").With(value => + responseDocument.Included[0].Relationships.Should().ContainKey("preferences").WhoseValue.With(value => { - value.ShouldNotBeNull(); + value.Should().NotBeNull(); value.Data.Value.Should().BeNull(); - value.Links.ShouldNotBeNull(); - value.Links.Self.ShouldNotBeNull(); - value.Links.Related.ShouldNotBeNull(); + value.Links.Should().NotBeNull(); + value.Links.Self.Should().NotBeNull(); + value.Links.Related.Should().NotBeNull(); }); 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.Author.ShouldNotBeNull(); + postCaptured.Author.Should().NotBeNull(); postCaptured.Author.DisplayName.Should().Be(post.Author.DisplayName); postCaptured.Author.EmailAddress.Should().Be(post.Author.EmailAddress); postCaptured.Author.UserName.Should().BeNull(); @@ -316,8 +316,8 @@ public async Task Can_select_fields_of_OneToMany_relationship() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - WebAccount account = _fakers.WebAccount.Generate(); - account.Posts = _fakers.BlogPost.Generate(1); + WebAccount account = _fakers.WebAccount.GenerateOne(); + account.Posts = _fakers.BlogPost.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -333,39 +333,39 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(account.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("displayName").With(value => value.Should().Be(account.DisplayName)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("displayName").WhoseValue.Should().Be(account.DisplayName); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("posts").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("posts").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.ManyValue.ShouldHaveCount(1); + value.Should().NotBeNull(); + value.Data.ManyValue.Should().HaveCount(1); value.Data.ManyValue[0].Id.Should().Be(account.Posts[0].StringId); - value.Links.ShouldNotBeNull(); - value.Links.Self.ShouldNotBeNull(); - value.Links.Related.ShouldNotBeNull(); + value.Links.Should().NotBeNull(); + value.Links.Self.Should().NotBeNull(); + value.Links.Related.Should().NotBeNull(); }); - responseDocument.Included.ShouldHaveCount(1); - responseDocument.Included[0].Attributes.ShouldHaveCount(1); - responseDocument.Included[0].Attributes.ShouldContainKey("caption").With(value => value.Should().Be(account.Posts[0].Caption)); - responseDocument.Included[0].Relationships.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); + responseDocument.Included[0].Attributes.Should().HaveCount(1); + responseDocument.Included[0].Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(account.Posts[0].Caption); + responseDocument.Included[0].Relationships.Should().HaveCount(1); - responseDocument.Included[0].Relationships.ShouldContainKey("labels").With(value => + responseDocument.Included[0].Relationships.Should().ContainKey("labels").WhoseValue.With(value => { - value.ShouldNotBeNull(); + value.Should().NotBeNull(); value.Data.Value.Should().BeNull(); - value.Links.ShouldNotBeNull(); - value.Links.Self.ShouldNotBeNull(); - value.Links.Related.ShouldNotBeNull(); + value.Links.Should().NotBeNull(); + value.Links.Self.Should().NotBeNull(); + value.Links.Related.Should().NotBeNull(); }); var accountCaptured = (WebAccount)store.Resources.Should().ContainSingle(resource => resource is WebAccount).Which; accountCaptured.Id.Should().Be(account.Id); accountCaptured.DisplayName.Should().Be(account.DisplayName); - accountCaptured.Posts.ShouldHaveCount(1); + accountCaptured.Posts.Should().HaveCount(1); accountCaptured.Posts[0].Caption.Should().Be(account.Posts[0].Caption); accountCaptured.Posts[0].Url.Should().BeNull(); } @@ -377,9 +377,9 @@ public async Task Can_select_fields_of_OneToMany_relationship_at_secondary_endpo var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Blog blog = _fakers.Blog.Generate(); - blog.Owner = _fakers.WebAccount.Generate(); - blog.Owner.Posts = _fakers.BlogPost.Generate(1); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Owner = _fakers.WebAccount.GenerateOne(); + blog.Owner.Posts = _fakers.BlogPost.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -395,40 +395,40 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(blog.Owner.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("displayName").With(value => value.Should().Be(blog.Owner.DisplayName)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("displayName").WhoseValue.Should().Be(blog.Owner.DisplayName); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("posts").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("posts").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.ManyValue.ShouldHaveCount(1); + value.Should().NotBeNull(); + value.Data.ManyValue.Should().HaveCount(1); value.Data.ManyValue[0].Id.Should().Be(blog.Owner.Posts[0].StringId); - value.Links.ShouldNotBeNull(); - value.Links.Self.ShouldNotBeNull(); - value.Links.Related.ShouldNotBeNull(); + value.Links.Should().NotBeNull(); + value.Links.Self.Should().NotBeNull(); + value.Links.Related.Should().NotBeNull(); }); - responseDocument.Included.ShouldHaveCount(1); - responseDocument.Included[0].Attributes.ShouldHaveCount(1); - responseDocument.Included[0].Attributes.ShouldContainKey("caption").With(value => value.Should().Be(blog.Owner.Posts[0].Caption)); - responseDocument.Included[0].Relationships.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); + responseDocument.Included[0].Attributes.Should().HaveCount(1); + responseDocument.Included[0].Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(blog.Owner.Posts[0].Caption); + responseDocument.Included[0].Relationships.Should().HaveCount(1); - responseDocument.Included[0].Relationships.ShouldContainKey("comments").With(value => + responseDocument.Included[0].Relationships.Should().ContainKey("comments").WhoseValue.With(value => { - value.ShouldNotBeNull(); + value.Should().NotBeNull(); value.Data.Value.Should().BeNull(); - value.Links.ShouldNotBeNull(); - value.Links.Self.ShouldNotBeNull(); - value.Links.Related.ShouldNotBeNull(); + value.Links.Should().NotBeNull(); + value.Links.Self.Should().NotBeNull(); + value.Links.Related.Should().NotBeNull(); }); var blogCaptured = (Blog)store.Resources.Should().ContainSingle(resource => resource is Blog).Which; blogCaptured.Id.Should().Be(blog.Id); - blogCaptured.Owner.ShouldNotBeNull(); + blogCaptured.Owner.Should().NotBeNull(); blogCaptured.Owner.DisplayName.Should().Be(blog.Owner.DisplayName); - blogCaptured.Owner.Posts.ShouldHaveCount(1); + blogCaptured.Owner.Posts.Should().HaveCount(1); blogCaptured.Owner.Posts[0].Caption.Should().Be(blog.Owner.Posts[0].Caption); blogCaptured.Owner.Posts[0].Url.Should().BeNull(); } @@ -440,8 +440,8 @@ public async Task Can_select_fields_of_ManyToMany_relationship() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - BlogPost post = _fakers.BlogPost.Generate(); - post.Labels = _fakers.Label.Generate(1).ToHashSet(); + BlogPost post = _fakers.BlogPost.GenerateOne(); + post.Labels = _fakers.Label.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -457,30 +457,30 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(post.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("caption").With(value => value.Should().Be(post.Caption)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(post.Caption); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("labels").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("labels").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.ManyValue.ShouldHaveCount(1); + value.Should().NotBeNull(); + value.Data.ManyValue.Should().HaveCount(1); value.Data.ManyValue[0].Id.Should().Be(post.Labels.ElementAt(0).StringId); - value.Links.ShouldNotBeNull(); - value.Links.Self.ShouldNotBeNull(); - value.Links.Related.ShouldNotBeNull(); + value.Links.Should().NotBeNull(); + value.Links.Self.Should().NotBeNull(); + value.Links.Related.Should().NotBeNull(); }); - responseDocument.Included.ShouldHaveCount(1); - responseDocument.Included[0].Attributes.ShouldHaveCount(1); - responseDocument.Included[0].Attributes.ShouldContainKey("color").With(value => value.Should().Be(post.Labels.Single().Color)); + responseDocument.Included.Should().HaveCount(1); + responseDocument.Included[0].Attributes.Should().HaveCount(1); + responseDocument.Included[0].Attributes.Should().ContainKey("color").WhoseValue.Should().Be(post.Labels.Single().Color); responseDocument.Included[0].Relationships.Should().BeNull(); 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.Labels.ShouldHaveCount(1); + postCaptured.Labels.Should().HaveCount(1); postCaptured.Labels.Single().Color.Should().Be(post.Labels.Single().Color); postCaptured.Labels.Single().Name.Should().BeNull(); } @@ -492,9 +492,9 @@ public async Task Can_select_attributes_in_multiple_resource_types() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Blog blog = _fakers.Blog.Generate(); - blog.Owner = _fakers.WebAccount.Generate(); - blog.Owner.Posts = _fakers.BlogPost.Generate(1); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Owner = _fakers.WebAccount.GenerateOne(); + blog.Owner.Posts = _fakers.BlogPost.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -510,26 +510,26 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("blogs"); responseDocument.Data.SingleValue.Id.Should().Be(blog.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldHaveCount(1); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("title").With(value => value.Should().Be(blog.Title)); + responseDocument.Data.SingleValue.Attributes.Should().HaveCount(1); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(blog.Title); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); - responseDocument.Included.ShouldHaveCount(2); + responseDocument.Included.Should().HaveCount(2); responseDocument.Included[0].Type.Should().Be("webAccounts"); responseDocument.Included[0].Id.Should().Be(blog.Owner.StringId); - responseDocument.Included[0].Attributes.ShouldHaveCount(2); - responseDocument.Included[0].Attributes.ShouldContainKey("userName").With(value => value.Should().Be(blog.Owner.UserName)); - responseDocument.Included[0].Attributes.ShouldContainKey("displayName").With(value => value.Should().Be(blog.Owner.DisplayName)); + responseDocument.Included[0].Attributes.Should().HaveCount(2); + responseDocument.Included[0].Attributes.Should().ContainKey("userName").WhoseValue.Should().Be(blog.Owner.UserName); + responseDocument.Included[0].Attributes.Should().ContainKey("displayName").WhoseValue.Should().Be(blog.Owner.DisplayName); responseDocument.Included[0].Relationships.Should().BeNull(); responseDocument.Included[1].Type.Should().Be("blogPosts"); responseDocument.Included[1].Id.Should().Be(blog.Owner.Posts[0].StringId); - responseDocument.Included[1].Attributes.ShouldHaveCount(1); - responseDocument.Included[1].Attributes.ShouldContainKey("caption").With(value => value.Should().Be(blog.Owner.Posts[0].Caption)); + responseDocument.Included[1].Attributes.Should().HaveCount(1); + responseDocument.Included[1].Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(blog.Owner.Posts[0].Caption); responseDocument.Included[1].Relationships.Should().BeNull(); var blogCaptured = (Blog)store.Resources.Should().ContainSingle(resource => resource is Blog).Which; @@ -541,7 +541,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => blogCaptured.Owner.DisplayName.Should().Be(blog.Owner.DisplayName); blogCaptured.Owner.DateOfBirth.Should().BeNull(); - blogCaptured.Owner.Posts.ShouldHaveCount(1); + blogCaptured.Owner.Posts.Should().HaveCount(1); blogCaptured.Owner.Posts[0].Caption.Should().Be(blog.Owner.Posts[0].Caption); blogCaptured.Owner.Posts[0].Url.Should().BeNull(); } @@ -553,9 +553,9 @@ public async Task Can_select_only_top_level_fields_with_multiple_includes() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Blog blog = _fakers.Blog.Generate(); - blog.Owner = _fakers.WebAccount.Generate(); - blog.Owner.Posts = _fakers.BlogPost.Generate(1); + Blog blog = _fakers.Blog.GenerateOne(); + blog.Owner = _fakers.WebAccount.GenerateOne(); + blog.Owner.Posts = _fakers.BlogPost.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -571,53 +571,53 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("blogs"); responseDocument.Data.SingleValue.Id.Should().Be(blog.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldHaveCount(1); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("title").With(value => value.Should().Be(blog.Title)); - responseDocument.Data.SingleValue.Relationships.ShouldHaveCount(1); + responseDocument.Data.SingleValue.Attributes.Should().HaveCount(1); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(blog.Title); + responseDocument.Data.SingleValue.Relationships.Should().HaveCount(1); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("owner").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("owner").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.SingleValue.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Data.SingleValue.Should().NotBeNull(); value.Data.SingleValue.Id.Should().Be(blog.Owner.StringId); - value.Links.ShouldNotBeNull(); - value.Links.Self.ShouldNotBeNull(); - value.Links.Related.ShouldNotBeNull(); + value.Links.Should().NotBeNull(); + value.Links.Self.Should().NotBeNull(); + value.Links.Related.Should().NotBeNull(); }); - responseDocument.Included.ShouldHaveCount(2); + responseDocument.Included.Should().HaveCount(2); responseDocument.Included[0].Type.Should().Be("webAccounts"); responseDocument.Included[0].Id.Should().Be(blog.Owner.StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("userName").With(value => value.Should().Be(blog.Owner.UserName)); - responseDocument.Included[0].Attributes.ShouldContainKey("displayName").With(value => value.Should().Be(blog.Owner.DisplayName)); - responseDocument.Included[0].Attributes.ShouldContainKey("dateOfBirth").With(value => value.Should().Be(blog.Owner.DateOfBirth)); + responseDocument.Included[0].Attributes.Should().ContainKey("userName").WhoseValue.Should().Be(blog.Owner.UserName); + responseDocument.Included[0].Attributes.Should().ContainKey("displayName").WhoseValue.Should().Be(blog.Owner.DisplayName); + responseDocument.Included[0].Attributes.Should().ContainKey("dateOfBirth").WhoseValue.Should().Be(blog.Owner.DateOfBirth); - responseDocument.Included[0].Relationships.ShouldContainKey("posts").With(value => + responseDocument.Included[0].Relationships.Should().ContainKey("posts").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.ManyValue.ShouldHaveCount(1); + value.Should().NotBeNull(); + value.Data.ManyValue.Should().HaveCount(1); value.Data.ManyValue[0].Id.Should().Be(blog.Owner.Posts[0].StringId); - value.Links.ShouldNotBeNull(); - value.Links.Self.ShouldNotBeNull(); - value.Links.Related.ShouldNotBeNull(); + value.Links.Should().NotBeNull(); + value.Links.Self.Should().NotBeNull(); + value.Links.Related.Should().NotBeNull(); }); responseDocument.Included[1].Type.Should().Be("blogPosts"); responseDocument.Included[1].Id.Should().Be(blog.Owner.Posts[0].StringId); - responseDocument.Included[1].Attributes.ShouldContainKey("caption").With(value => value.Should().Be(blog.Owner.Posts[0].Caption)); - responseDocument.Included[1].Attributes.ShouldContainKey("url").With(value => value.Should().Be(blog.Owner.Posts[0].Url)); + responseDocument.Included[1].Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(blog.Owner.Posts[0].Caption); + responseDocument.Included[1].Attributes.Should().ContainKey("url").WhoseValue.Should().Be(blog.Owner.Posts[0].Url); - responseDocument.Included[1].Relationships.ShouldContainKey("labels").With(value => + responseDocument.Included[1].Relationships.Should().ContainKey("labels").WhoseValue.With(value => { - value.ShouldNotBeNull(); + value.Should().NotBeNull(); value.Data.Value.Should().BeNull(); - value.Links.ShouldNotBeNull(); - value.Links.Self.ShouldNotBeNull(); - value.Links.Related.ShouldNotBeNull(); + value.Links.Should().NotBeNull(); + value.Links.Self.Should().NotBeNull(); + value.Links.Related.Should().NotBeNull(); }); var blogCaptured = (Blog)store.Resources.Should().ContainSingle(resource => resource is Blog).Which; @@ -633,7 +633,7 @@ public async Task Can_select_ID() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -650,10 +650,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(post.StringId); - responseDocument.Data.ManyValue[0].Attributes.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("caption").With(value => value.Should().Be(post.Caption)); + responseDocument.Data.ManyValue[0].Attributes.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(post.Caption); responseDocument.Data.ManyValue[0].Relationships.Should().BeNull(); var postCaptured = (BlogPost)store.Resources.Should().ContainSingle(resource => resource is BlogPost).Which; @@ -669,7 +669,7 @@ public async Task Can_select_empty_fieldset() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -686,7 +686,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(post.StringId); responseDocument.Data.ManyValue[0].Attributes.Should().BeNull(); responseDocument.Data.ManyValue[0].Relationships.Should().BeNull(); @@ -709,13 +709,13 @@ public async Task Cannot_select_on_unknown_resource_type() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified fieldset is invalid."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist. {parameterName}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be(parameterName.Text); } @@ -723,7 +723,7 @@ public async Task Cannot_select_on_unknown_resource_type() public async Task Cannot_select_attribute_with_blocked_capability() { // Arrange - WebAccount account = _fakers.WebAccount.Generate(); + WebAccount account = _fakers.WebAccount.GenerateOne(); var parameterValue = new MarkedText("^password", '^'); string route = $"/webAccounts/{account.Id}?fields[webAccounts]={parameterValue.Text}"; @@ -734,13 +734,13 @@ public async Task Cannot_select_attribute_with_blocked_capability() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified fieldset is invalid."); error.Detail.Should().Be($"Retrieving the attribute 'password' is not allowed. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("fields[webAccounts]"); } @@ -748,7 +748,7 @@ public async Task Cannot_select_attribute_with_blocked_capability() public async Task Cannot_select_ToOne_relationship_with_blocked_capability() { // Arrange - WebAccount account = _fakers.WebAccount.Generate(); + WebAccount account = _fakers.WebAccount.GenerateOne(); var parameterValue = new MarkedText("^person", '^'); string route = $"/webAccounts/{account.Id}?fields[webAccounts]={parameterValue.Text}"; @@ -759,13 +759,13 @@ public async Task Cannot_select_ToOne_relationship_with_blocked_capability() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified fieldset is invalid."); error.Detail.Should().Be($"Retrieving the relationship 'person' is not allowed. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("fields[webAccounts]"); } @@ -773,7 +773,7 @@ public async Task Cannot_select_ToOne_relationship_with_blocked_capability() public async Task Cannot_select_ToMany_relationship_with_blocked_capability() { // Arrange - Calendar calendar = _fakers.Calendar.Generate(); + Calendar calendar = _fakers.Calendar.GenerateOne(); var parameterValue = new MarkedText("^appointments", '^'); string route = $"/calendars/{calendar.Id}?fields[calendars]={parameterValue.Text}"; @@ -784,13 +784,13 @@ public async Task Cannot_select_ToMany_relationship_with_blocked_capability() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified fieldset is invalid."); error.Detail.Should().Be($"Retrieving the relationship 'appointments' is not allowed. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("fields[calendars]"); } @@ -801,7 +801,7 @@ public async Task Fetches_all_scalar_properties_when_fieldset_contains_readonly_ var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - Blog blog = _fakers.Blog.Generate(); + Blog blog = _fakers.Blog.GenerateOne(); blog.IsPublished = true; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -818,10 +818,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(blog.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldHaveCount(1); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("showAdvertisements").With(value => value.Should().Be(blog.ShowAdvertisements)); + responseDocument.Data.SingleValue.Attributes.Should().HaveCount(1); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("showAdvertisements").WhoseValue.Should().Be(blog.ShowAdvertisements); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); var blogCaptured = (Blog)store.Resources.Should().ContainSingle(resource => resource is Blog).Which; @@ -837,7 +837,7 @@ public async Task Can_select_fields_on_resource_type_multiple_times() var store = _testContext.Factory.Services.GetRequiredService(); store.Clear(); - BlogPost post = _fakers.BlogPost.Generate(); + BlogPost post = _fakers.BlogPost.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -853,20 +853,20 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(post.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldHaveCount(2); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("caption").With(value => value.Should().Be(post.Caption)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("url").With(value => value.Should().Be(post.Url)); - responseDocument.Data.SingleValue.Relationships.ShouldHaveCount(1); + responseDocument.Data.SingleValue.Attributes.Should().HaveCount(2); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("caption").WhoseValue.Should().Be(post.Caption); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("url").WhoseValue.Should().Be(post.Url); + responseDocument.Data.SingleValue.Relationships.Should().HaveCount(1); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("author").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("author").WhoseValue.With(value => { - value.ShouldNotBeNull(); + value.Should().NotBeNull(); value.Data.Value.Should().BeNull(); - value.Links.ShouldNotBeNull(); - value.Links.Self.ShouldNotBeNull(); - value.Links.Related.ShouldNotBeNull(); + value.Links.Should().NotBeNull(); + value.Links.Self.Should().NotBeNull(); + value.Links.Related.Should().NotBeNull(); }); var postCaptured = (BlogPost)store.Resources.Should().ContainSingle(resource => resource is BlogPost).Which; @@ -879,8 +879,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Returns_related_resources_on_broken_resource_linkage() { // Arrange - WebAccount account = _fakers.WebAccount.Generate(); - account.Posts = _fakers.BlogPost.Generate(2); + WebAccount account = _fakers.WebAccount.GenerateOne(); + account.Posts = _fakers.BlogPost.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -896,11 +896,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(account.StringId); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); - responseDocument.Included.ShouldHaveCount(2); - responseDocument.Included.Should().OnlyContain(resourceObject => resourceObject.Type == "blogPosts"); + responseDocument.Included.Should().HaveCount(2); + responseDocument.Included.Should().OnlyContain(resource => resource.Type == "blogPosts"); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/AssignIdToRgbColorDefinition.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/AssignIdToRgbColorDefinition.cs new file mode 100644 index 0000000000..d13bf4e37e --- /dev/null +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/AssignIdToRgbColorDefinition.cs @@ -0,0 +1,30 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.Resources; + +namespace JsonApiDotNetCoreTests.IntegrationTests.ReadWrite.Creating; + +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +internal sealed class AssignIdToRgbColorDefinition(IResourceGraph resourceGraph) + : JsonApiResourceDefinition(resourceGraph) +{ + internal const string DefaultId = "0x000000"; + internal const string DefaultName = "Black"; + + public override Task OnWritingAsync(RgbColor resource, WriteOperationKind writeOperation, CancellationToken cancellationToken) + { + if (writeOperation == WriteOperationKind.CreateResource && resource.Id == null) + { + SetDefaultColor(resource); + } + + return Task.CompletedTask; + } + + private static void SetDefaultColor(RgbColor resource) + { + resource.Id = DefaultId; + resource.DisplayName = DefaultName; + } +} diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceTests.cs index 39af545d0c..004fcb2121 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceTests.cs @@ -35,7 +35,7 @@ public CreateResourceTests(IntegrationTestContext value.Should().Be(newWorkItem.Description)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("dueAt").With(value => value.Should().Be(newWorkItem.DueAt)); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("description").WhoseValue.Should().Be(newWorkItem.Description); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("dueAt").WhoseValue.Should().Be(newWorkItem.DueAt); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); - int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -113,15 +113,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }); PropertyInfo? property = typeof(WorkItem).GetProperty(nameof(Identifiable.Id)); - property.ShouldNotBeNull(); - property.PropertyType.Should().Be(typeof(int)); + property.Should().NotBeNull(); + property.PropertyType.Should().Be(); } [Fact] public async Task Can_create_resource_with_long_ID() { // Arrange - UserAccount newUserAccount = _fakers.UserAccount.Generate(); + UserAccount newUserAccount = _fakers.UserAccount.GenerateOne(); var requestBody = new { @@ -144,13 +144,13 @@ public async Task Can_create_resource_with_long_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("userAccounts"); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("firstName").With(value => value.Should().Be(newUserAccount.FirstName)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("lastName").With(value => value.Should().Be(newUserAccount.LastName)); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("firstName").WhoseValue.Should().Be(newUserAccount.FirstName); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("lastName").WhoseValue.Should().Be(newUserAccount.LastName); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); - long newUserAccountId = long.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + long newUserAccountId = long.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -161,15 +161,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }); PropertyInfo? property = typeof(UserAccount).GetProperty(nameof(Identifiable.Id)); - property.ShouldNotBeNull(); - property.PropertyType.Should().Be(typeof(long)); + property.Should().NotBeNull(); + property.PropertyType.Should().Be(); } [Fact] public async Task Can_create_resource_with_guid_ID() { // Arrange - WorkItemGroup newGroup = _fakers.WorkItemGroup.Generate(); + WorkItemGroup newGroup = _fakers.WorkItemGroup.GenerateOne(); var requestBody = new { @@ -191,12 +191,12 @@ public async Task Can_create_resource_with_guid_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("workItemGroups"); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("name").With(value => value.Should().Be(newGroup.Name)); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(newGroup.Name); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); - Guid newGroupId = Guid.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + Guid newGroupId = Guid.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -206,8 +206,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }); PropertyInfo? property = typeof(WorkItemGroup).GetProperty(nameof(Identifiable.Id)); - property.ShouldNotBeNull(); - property.PropertyType.Should().Be(typeof(Guid)); + property.Should().NotBeNull(); + property.PropertyType.Should().Be(); } [Fact] @@ -236,13 +236,13 @@ public async Task Can_create_resource_without_attributes_or_relationships() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("workItems"); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("description").With(value => value.Should().BeNull()); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("dueAt").With(value => value.Should().BeNull()); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("description").WhoseValue.Should().BeNull(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("dueAt").WhoseValue.Should().BeNull(); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); - int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -257,7 +257,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_resource_with_unknown_attribute() { // Arrange - WorkItem newWorkItem = _fakers.WorkItem.Generate(); + WorkItem newWorkItem = _fakers.WorkItem.GenerateOne(); var requestBody = new { @@ -280,15 +280,15 @@ public async Task Cannot_create_resource_with_unknown_attribute() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown attribute found."); error.Detail.Should().Be("Attribute 'doesNotExist' does not exist on resource type 'workItems'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/attributes/doesNotExist"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -298,7 +298,7 @@ public async Task Can_create_resource_with_unknown_attribute() var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.AllowUnknownFieldsInRequestBody = true; - WorkItem newWorkItem = _fakers.WorkItem.Generate(); + WorkItem newWorkItem = _fakers.WorkItem.GenerateOne(); var requestBody = new { @@ -321,12 +321,12 @@ public async Task Can_create_resource_with_unknown_attribute() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("workItems"); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("description").With(value => value.Should().Be(newWorkItem.Description)); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("description").WhoseValue.Should().Be(newWorkItem.Description); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); - int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -367,15 +367,15 @@ public async Task Cannot_create_resource_with_unknown_relationship() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown relationship found."); error.Detail.Should().Be("Relationship 'doesNotExist' does not exist on resource type 'workItems'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/doesNotExist"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -412,18 +412,18 @@ public async Task Can_create_resource_with_unknown_relationship() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("workItems"); - responseDocument.Data.SingleValue.Attributes.ShouldNotBeEmpty(); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Attributes.Should().NotBeEmpty(); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); - int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem? workItemInDatabase = await dbContext.WorkItems.FirstWithIdOrDefaultAsync(newWorkItemId); - workItemInDatabase.ShouldNotBeNull(); + workItemInDatabase.Should().NotBeNull(); }); } @@ -452,15 +452,15 @@ public async Task Cannot_create_resource_with_client_generated_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); error.Title.Should().Be("Failed to deserialize request body: The use of client-generated IDs is disabled."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/id"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -477,10 +477,10 @@ public async Task Cannot_create_resource_for_missing_request_body() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - httpResponse.Content.Headers.ContentType.ShouldNotBeNull(); - httpResponse.Content.Headers.ContentType.ToString().Should().Be(HeaderConstants.MediaType); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); @@ -504,14 +504,14 @@ public async Task Cannot_create_resource_for_null_request_body() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object, instead of 'null'."); error.Detail.Should().BeNull(); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -534,14 +534,14 @@ public async Task Cannot_create_resource_for_missing_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'data' element is required."); error.Detail.Should().BeNull(); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -561,15 +561,15 @@ public async Task Cannot_create_resource_for_null_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object, instead of 'null'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -595,15 +595,15 @@ public async Task Cannot_create_resource_for_array_data() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object, instead of an array."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -628,15 +628,15 @@ public async Task Cannot_create_resource_for_missing_type() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -662,15 +662,15 @@ public async Task Cannot_create_resource_for_unknown_type() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -720,15 +720,15 @@ public async Task Cannot_create_on_resource_type_mismatch_between_url_and_body() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Incompatible resource type found."); error.Detail.Should().Be("Type 'rgbColors' is not convertible to type 'workItems'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -755,15 +755,15 @@ public async Task Cannot_create_resource_with_readonly_attribute() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Attribute is read-only."); error.Detail.Should().Be("Attribute 'isDeprecated' on resource type 'workItemGroups' is read-only."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/attributes/isDeprecated"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -780,14 +780,14 @@ public async Task Cannot_create_resource_for_broken_JSON_request_body() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body."); error.Detail.Should().StartWith("'{' is invalid after a property name."); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -814,25 +814,25 @@ public async Task Cannot_create_resource_with_incompatible_attribute_value() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Incompatible attribute value found."); error.Detail.Should().Be("Failed to convert attribute 'dueAt' with value 'not-a-valid-time' of type 'String' to type 'Nullable'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/attributes/dueAt"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_create_resource_with_attributes_and_multiple_relationship_types() { // Arrange - List existingUserAccounts = _fakers.UserAccount.Generate(2); - WorkTag existingTag = _fakers.WorkTag.Generate(); + List existingUserAccounts = _fakers.UserAccount.GenerateList(2); + WorkTag existingTag = _fakers.WorkTag.GenerateOne(); - string newDescription = _fakers.WorkItem.Generate().Description!; + string newDescription = _fakers.WorkItem.GenerateOne().Description!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -894,11 +894,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("description").With(value => value.Should().Be(newDescription)); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("description").WhoseValue.Should().Be(newDescription); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); - int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -916,13 +916,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => workItemInDatabase.Description.Should().Be(newDescription); - workItemInDatabase.Assignee.ShouldNotBeNull(); + workItemInDatabase.Assignee.Should().NotBeNull(); workItemInDatabase.Assignee.Id.Should().Be(existingUserAccounts[0].Id); - workItemInDatabase.Subscribers.ShouldHaveCount(1); + workItemInDatabase.Subscribers.Should().HaveCount(1); workItemInDatabase.Subscribers.Single().Id.Should().Be(existingUserAccounts[1].Id); - workItemInDatabase.Tags.ShouldHaveCount(1); + workItemInDatabase.Tags.Should().HaveCount(1); workItemInDatabase.Tags.Single().Id.Should().Be(existingTag.Id); }); } @@ -951,14 +951,14 @@ public async Task Cannot_assign_attribute_with_blocked_capability() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Attribute value cannot be assigned when creating resource."); error.Detail.Should().Be("The attribute 'isImportant' on resource type 'workItems' cannot be assigned to."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/attributes/isImportant"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithClientGeneratedIdTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithClientGeneratedIdTests.cs index 92c88d72a4..681dc034c2 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithClientGeneratedIdTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithClientGeneratedIdTests.cs @@ -21,18 +21,25 @@ public CreateResourceWithClientGeneratedIdTests(IntegrationTestContext(); testContext.UseController(); + testContext.UseController(); - testContext.ConfigureServices(services => services.AddResourceDefinition()); - - var options = (JsonApiOptions)testContext.Factory.Services.GetRequiredService(); - options.ClientIdGeneration = ClientIdGenerationMode.Required; + testContext.ConfigureServices(services => + { + services.AddResourceDefinition(); + services.AddResourceDefinition(); + }); } - [Fact] - public async Task Can_create_resource_with_client_generated_guid_ID_having_side_effects() + [Theory] + [InlineData(ClientIdGenerationMode.Allowed)] + [InlineData(ClientIdGenerationMode.Required)] + public async Task Can_create_resource_with_client_generated_guid_ID_having_side_effects(ClientIdGenerationMode mode) { // Arrange - WorkItemGroup newGroup = _fakers.WorkItemGroup.Generate(); + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.ClientIdGeneration = mode; + + WorkItemGroup newGroup = _fakers.WorkItemGroup.GenerateOne(); newGroup.Id = Guid.NewGuid(); var requestBody = new @@ -58,11 +65,11 @@ public async Task Can_create_resource_with_client_generated_guid_ID_having_side_ string groupName = $"{newGroup.Name}{ImplicitlyChangingWorkItemGroupDefinition.Suffix}"; - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("workItemGroups"); responseDocument.Data.SingleValue.Id.Should().Be(newGroup.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("name").With(value => value.Should().Be(groupName)); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(groupName); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -72,15 +79,20 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }); PropertyInfo? property = typeof(WorkItemGroup).GetProperty(nameof(Identifiable.Id)); - property.ShouldNotBeNull(); - property.PropertyType.Should().Be(typeof(Guid)); + property.Should().NotBeNull(); + property.PropertyType.Should().Be(); } - [Fact] - public async Task Can_create_resource_with_client_generated_guid_ID_having_side_effects_with_fieldset() + [Theory] + [InlineData(ClientIdGenerationMode.Allowed)] + [InlineData(ClientIdGenerationMode.Required)] + public async Task Can_create_resource_with_client_generated_guid_ID_having_side_effects_with_fieldset(ClientIdGenerationMode mode) { // Arrange - WorkItemGroup newGroup = _fakers.WorkItemGroup.Generate(); + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.ClientIdGeneration = mode; + + WorkItemGroup newGroup = _fakers.WorkItemGroup.GenerateOne(); newGroup.Id = Guid.NewGuid(); var requestBody = new @@ -106,11 +118,11 @@ public async Task Can_create_resource_with_client_generated_guid_ID_having_side_ string groupName = $"{newGroup.Name}{ImplicitlyChangingWorkItemGroupDefinition.Suffix}"; - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("workItemGroups"); responseDocument.Data.SingleValue.Id.Should().Be(newGroup.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldHaveCount(1); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("name").With(value => value.Should().Be(groupName)); + responseDocument.Data.SingleValue.Attributes.Should().HaveCount(1); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(groupName); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); await _testContext.RunOnDatabaseAsync(async dbContext => @@ -121,15 +133,25 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }); PropertyInfo? property = typeof(WorkItemGroup).GetProperty(nameof(Identifiable.Id)); - property.ShouldNotBeNull(); - property.PropertyType.Should().Be(typeof(Guid)); + property.Should().NotBeNull(); + property.PropertyType.Should().Be(); } - [Fact] - public async Task Can_create_resource_with_client_generated_string_ID_having_no_side_effects() + [Theory] + [InlineData(ClientIdGenerationMode.Allowed)] + [InlineData(ClientIdGenerationMode.Required)] + public async Task Can_create_resource_with_client_generated_string_ID_having_no_side_effects(ClientIdGenerationMode mode) { // Arrange - RgbColor newColor = _fakers.RgbColor.Generate(); + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.ClientIdGeneration = mode; + + RgbColor newColor = _fakers.RgbColor.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + }); var requestBody = new { @@ -162,15 +184,25 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }); PropertyInfo? property = typeof(RgbColor).GetProperty(nameof(Identifiable.Id)); - property.ShouldNotBeNull(); - property.PropertyType.Should().Be(typeof(string)); + property.Should().NotBeNull(); + property.PropertyType.Should().Be(); } - [Fact] - public async Task Can_create_resource_with_client_generated_string_ID_having_no_side_effects_with_fieldset() + [Theory] + [InlineData(ClientIdGenerationMode.Allowed)] + [InlineData(ClientIdGenerationMode.Required)] + public async Task Can_create_resource_with_client_generated_string_ID_having_no_side_effects_with_fieldset(ClientIdGenerationMode mode) { // Arrange - RgbColor newColor = _fakers.RgbColor.Generate(); + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.ClientIdGeneration = mode; + + RgbColor newColor = _fakers.RgbColor.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + }); var requestBody = new { @@ -203,15 +235,80 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }); PropertyInfo? property = typeof(RgbColor).GetProperty(nameof(Identifiable.Id)); - property.ShouldNotBeNull(); - property.PropertyType.Should().Be(typeof(string)); + property.Should().NotBeNull(); + property.PropertyType.Should().Be(); } - [Fact] - public async Task Cannot_create_resource_for_missing_client_generated_ID() + [Theory] + [InlineData(ClientIdGenerationMode.Allowed)] + public async Task Can_create_resource_for_missing_client_generated_ID_having_side_effects(ClientIdGenerationMode mode) { // Arrange - string newDisplayName = _fakers.RgbColor.Generate().DisplayName; + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.ClientIdGeneration = mode; + + string newDisplayName = _fakers.RgbColor.GenerateOne().DisplayName; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + }); + + var requestBody = new + { + data = new + { + type = "rgbColors", + attributes = new + { + displayName = newDisplayName + } + } + }; + + const string route = "/rgbColors"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); + + const string defaultId = AssignIdToRgbColorDefinition.DefaultId; + const string defaultName = AssignIdToRgbColorDefinition.DefaultName; + + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Type.Should().Be("rgbColors"); + responseDocument.Data.SingleValue.Id.Should().Be(defaultId); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("displayName").WhoseValue.Should().Be(defaultName); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + RgbColor colorInDatabase = await dbContext.RgbColors.FirstWithIdAsync((string?)defaultId); + + colorInDatabase.DisplayName.Should().Be(defaultName); + }); + + PropertyInfo? property = typeof(RgbColor).GetProperty(nameof(Identifiable.Id)); + property.Should().NotBeNull(); + property.PropertyType.Should().Be(); + } + + [Theory] + [InlineData(ClientIdGenerationMode.Required)] + public async Task Cannot_create_resource_for_missing_client_generated_ID(ClientIdGenerationMode mode) + { + // Arrange + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.ClientIdGeneration = mode; + + string newDisplayName = _fakers.RgbColor.GenerateOne().DisplayName; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + }); var requestBody = new { @@ -233,28 +330,259 @@ public async Task Cannot_create_resource_for_missing_client_generated_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); + error.Source.Pointer.Should().Be("/data"); + error.Meta.Should().HaveRequestBody(); + } + + [Theory] + [InlineData(ClientIdGenerationMode.Allowed)] + [InlineData(ClientIdGenerationMode.Required)] + public async Task Cannot_create_resource_with_client_generated_zero_guid_ID(ClientIdGenerationMode mode) + { + // Arrange + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.ClientIdGeneration = mode; + + WorkItemGroup newGroup = _fakers.WorkItemGroup.GenerateOne(); + + var requestBody = new + { + data = new + { + type = "workItemGroups", + id = Guid.Empty.ToString(), + attributes = new + { + name = newGroup.Name + } + } + }; + + const string route = "/workItemGroups"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); + + responseDocument.Errors.Should().HaveCount(1); + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); + error.Title.Should().Be("Failed to deserialize request body: The 'id' element is invalid."); + error.Detail.Should().BeNull(); + error.Source.Should().NotBeNull(); + error.Source.Pointer.Should().Be("/data"); + error.Meta.Should().HaveRequestBody(); + } + + [Theory] + [InlineData(ClientIdGenerationMode.Allowed)] + [InlineData(ClientIdGenerationMode.Required)] + public async Task Cannot_create_resource_with_client_generated_empty_guid_ID(ClientIdGenerationMode mode) + { + // Arrange + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.ClientIdGeneration = mode; + + WorkItemGroup newGroup = _fakers.WorkItemGroup.GenerateOne(); + + var requestBody = new + { + data = new + { + type = "workItemGroups", + id = string.Empty, + attributes = new + { + name = newGroup.Name + } + } + }; + + const string route = "/workItemGroups"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); + + responseDocument.Errors.Should().HaveCount(1); + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); + error.Title.Should().Be("Failed to deserialize request body: The 'id' element is invalid."); + error.Detail.Should().BeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } - [Fact] - public async Task Cannot_create_resource_for_existing_client_generated_ID() + [Theory] + [InlineData(ClientIdGenerationMode.Allowed)] + [InlineData(ClientIdGenerationMode.Required)] + public async Task Can_create_resource_with_client_generated_empty_string_ID(ClientIdGenerationMode mode) { // Arrange - RgbColor existingColor = _fakers.RgbColor.Generate(); + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.ClientIdGeneration = mode; - RgbColor colorToCreate = _fakers.RgbColor.Generate(); - colorToCreate.Id = existingColor.Id; + RgbColor newColor = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { + await dbContext.ClearTableAsync(); + }); + + var requestBody = new + { + data = new + { + type = "rgbColors", + id = string.Empty, + attributes = new + { + displayName = newColor.DisplayName + } + } + }; + + const string route = "/rgbColors?fields[rgbColors]=id"; + + // Act + (HttpResponseMessage httpResponse, string responseDocument) = await _testContext.ExecutePostAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NoContent); + + responseDocument.Should().BeEmpty(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + RgbColor colorInDatabase = await dbContext.RgbColors.FirstWithIdAsync((string?)string.Empty); + + colorInDatabase.DisplayName.Should().Be(newColor.DisplayName); + }); + + PropertyInfo? property = typeof(RgbColor).GetProperty(nameof(Identifiable.Id)); + property.Should().NotBeNull(); + property.PropertyType.Should().Be(); + } + + [Theory] + [InlineData(ClientIdGenerationMode.Allowed)] + [InlineData(ClientIdGenerationMode.Required)] + public async Task Cannot_create_resource_with_client_generated_zero_long_ID(ClientIdGenerationMode mode) + { + // Arrange + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.ClientIdGeneration = mode; + + UserAccount newAccount = _fakers.UserAccount.GenerateOne(); + + var requestBody = new + { + data = new + { + type = "userAccounts", + id = "0", + attributes = new + { + firstName = newAccount.FirstName, + lastName = newAccount.LastName + } + } + }; + + const string route = "/userAccounts"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); + + responseDocument.Errors.Should().HaveCount(1); + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); + error.Title.Should().Be("Failed to deserialize request body: The 'id' element is invalid."); + error.Detail.Should().BeNull(); + error.Source.Should().NotBeNull(); + error.Source.Pointer.Should().Be("/data"); + error.Meta.Should().HaveRequestBody(); + } + + [Theory] + [InlineData(ClientIdGenerationMode.Allowed)] + [InlineData(ClientIdGenerationMode.Required)] + public async Task Cannot_create_resource_with_client_generated_empty_long_ID(ClientIdGenerationMode mode) + { + // Arrange + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.ClientIdGeneration = mode; + + UserAccount newAccount = _fakers.UserAccount.GenerateOne(); + + var requestBody = new + { + data = new + { + type = "userAccounts", + id = string.Empty, + attributes = new + { + firstName = newAccount.FirstName, + lastName = newAccount.LastName + } + } + }; + + const string route = "/userAccounts"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); + + responseDocument.Errors.Should().HaveCount(1); + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); + error.Title.Should().Be("Failed to deserialize request body: The 'id' element is invalid."); + error.Detail.Should().BeNull(); + error.Source.Should().NotBeNull(); + error.Source.Pointer.Should().Be("/data"); + error.Meta.Should().HaveRequestBody(); + } + + [Theory] + [InlineData(ClientIdGenerationMode.Allowed)] + [InlineData(ClientIdGenerationMode.Required)] + public async Task Cannot_create_resource_for_existing_client_generated_ID(ClientIdGenerationMode mode) + { + // Arrange + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.ClientIdGeneration = mode; + + RgbColor existingColor = _fakers.RgbColor.GenerateOne(); + + RgbColor newColor = _fakers.RgbColor.GenerateOne(); + newColor.Id = existingColor.Id; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); dbContext.RgbColors.Add(existingColor); await dbContext.SaveChangesAsync(); }); @@ -264,10 +592,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => data = new { type = "rgbColors", - id = colorToCreate.StringId, + id = newColor.StringId, attributes = new { - displayName = colorToCreate.DisplayName + displayName = newColor.DisplayName } } }; @@ -280,7 +608,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToManyRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToManyRelationshipTests.cs index 0a6ed42c60..9323133ae1 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToManyRelationshipTests.cs @@ -25,7 +25,7 @@ public CreateResourceWithToManyRelationshipTests(IntegrationTestContext existingUserAccounts = _fakers.UserAccount.Generate(2); + List existingUserAccounts = _fakers.UserAccount.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -68,18 +68,18 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldNotBeEmpty(); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().NotBeEmpty(); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); responseDocument.Included.Should().BeNull(); - int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Subscribers).FirstWithIdAsync(newWorkItemId); - workItemInDatabase.Subscribers.ShouldHaveCount(2); + workItemInDatabase.Subscribers.Should().HaveCount(2); workItemInDatabase.Subscribers.Should().ContainSingle(subscriber => subscriber.Id == existingUserAccounts[0].Id); workItemInDatabase.Subscribers.Should().ContainSingle(subscriber => subscriber.Id == existingUserAccounts[1].Id); }); @@ -89,7 +89,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToMany_relationship_with_include() { // Arrange - List existingUserAccounts = _fakers.UserAccount.Generate(2); + List existingUserAccounts = _fakers.UserAccount.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -132,25 +132,25 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldNotBeEmpty(); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().NotBeEmpty(); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); - responseDocument.Included.ShouldHaveCount(2); + responseDocument.Included.Should().HaveCount(2); responseDocument.Included.Should().OnlyContain(resource => resource.Type == "userAccounts"); responseDocument.Included.Should().ContainSingle(resource => resource.Id == existingUserAccounts[0].StringId); responseDocument.Included.Should().ContainSingle(resource => resource.Id == existingUserAccounts[1].StringId); - responseDocument.Included.Should().OnlyContain(resource => resource.Attributes.ShouldContainKey("firstName") != null); - responseDocument.Included.Should().OnlyContain(resource => resource.Attributes.ShouldContainKey("lastName") != null); - responseDocument.Included.Should().OnlyContain(resource => resource.Relationships.ShouldNotBeNull().Count > 0); + responseDocument.Included.Should().OnlyContain(resource => resource.Attributes.Should().ContainKey2("firstName").WhoseValue != null); + responseDocument.Included.Should().OnlyContain(resource => resource.Attributes.Should().ContainKey2("lastName").WhoseValue != null); + responseDocument.Included.Should().OnlyContain(resource => resource.Relationships != null && resource.Relationships.Count > 0); - int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Subscribers).FirstWithIdAsync(newWorkItemId); - workItemInDatabase.Subscribers.ShouldHaveCount(2); + workItemInDatabase.Subscribers.Should().HaveCount(2); workItemInDatabase.Subscribers.Should().ContainSingle(userAccount => userAccount.Id == existingUserAccounts[0].Id); workItemInDatabase.Subscribers.Should().ContainSingle(userAccount => userAccount.Id == existingUserAccounts[1].Id); }); @@ -160,7 +160,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToMany_relationship_with_include_and_secondary_fieldset() { // Arrange - List existingUserAccounts = _fakers.UserAccount.Generate(2); + List existingUserAccounts = _fakers.UserAccount.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -203,25 +203,25 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldNotBeEmpty(); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().NotBeEmpty(); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); - responseDocument.Included.ShouldHaveCount(2); + responseDocument.Included.Should().HaveCount(2); responseDocument.Included.Should().OnlyContain(resource => resource.Type == "userAccounts"); responseDocument.Included.Should().ContainSingle(resource => resource.Id == existingUserAccounts[0].StringId); responseDocument.Included.Should().ContainSingle(resource => resource.Id == existingUserAccounts[1].StringId); - responseDocument.Included.Should().OnlyContain(resource => resource.Attributes.ShouldNotBeNull().Count == 1); - responseDocument.Included.Should().OnlyContain(resource => resource.Attributes.ShouldContainKey("firstName") != null); + responseDocument.Included.Should().OnlyContain(resource => resource.Attributes != null && resource.Attributes.Count == 1); + responseDocument.Included.Should().OnlyContain(resource => resource.Attributes.Should().ContainKey2("firstName").WhoseValue != null); responseDocument.Included.Should().OnlyContain(resource => resource.Relationships == null); - int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Subscribers).FirstWithIdAsync(newWorkItemId); - workItemInDatabase.Subscribers.ShouldHaveCount(2); + workItemInDatabase.Subscribers.Should().HaveCount(2); workItemInDatabase.Subscribers.Should().ContainSingle(userAccount => userAccount.Id == existingUserAccounts[0].Id); workItemInDatabase.Subscribers.Should().ContainSingle(userAccount => userAccount.Id == existingUserAccounts[1].Id); }); @@ -231,8 +231,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_ManyToMany_relationship_with_include_and_fieldsets() { // Arrange - List existingTags = _fakers.WorkTag.Generate(3); - WorkItem workItemToCreate = _fakers.WorkItem.Generate(); + List existingTags = _fakers.WorkTag.GenerateList(3); + WorkItem newWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -247,8 +247,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => type = "workItems", attributes = new { - description = workItemToCreate.Description, - priority = workItemToCreate.Priority + description = newWorkItem.Description, + priority = newWorkItem.Priority }, relationships = new { @@ -285,36 +285,36 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldHaveCount(1); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("priority").With(value => value.Should().Be(workItemToCreate.Priority)); - responseDocument.Data.SingleValue.Relationships.ShouldHaveCount(1); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().HaveCount(1); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("priority").WhoseValue.Should().Be(newWorkItem.Priority); + responseDocument.Data.SingleValue.Relationships.Should().HaveCount(1); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("tags").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("tags").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.ManyValue.ShouldHaveCount(3); + value.Should().NotBeNull(); + value.Data.ManyValue.Should().HaveCount(3); value.Data.ManyValue[0].Id.Should().Be(existingTags[0].StringId); value.Data.ManyValue[1].Id.Should().Be(existingTags[1].StringId); value.Data.ManyValue[2].Id.Should().Be(existingTags[2].StringId); }); - responseDocument.Included.ShouldHaveCount(3); + responseDocument.Included.Should().HaveCount(3); responseDocument.Included.Should().OnlyContain(resource => resource.Type == "workTags"); responseDocument.Included.Should().ContainSingle(resource => resource.Id == existingTags[0].StringId); responseDocument.Included.Should().ContainSingle(resource => resource.Id == existingTags[1].StringId); responseDocument.Included.Should().ContainSingle(resource => resource.Id == existingTags[2].StringId); - responseDocument.Included.Should().OnlyContain(resource => resource.Attributes.ShouldNotBeNull().Count == 1); - responseDocument.Included.Should().OnlyContain(resource => resource.Attributes.ShouldContainKey("text") != null); + responseDocument.Included.Should().OnlyContain(resource => resource.Attributes != null && resource.Attributes.Count == 1); + responseDocument.Included.Should().OnlyContain(resource => resource.Attributes.Should().ContainKey2("text").WhoseValue != null); responseDocument.Included.Should().OnlyContain(resource => resource.Relationships == null); - int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Tags).FirstWithIdAsync(newWorkItemId); - workItemInDatabase.Tags.ShouldHaveCount(3); + workItemInDatabase.Tags.Should().HaveCount(3); workItemInDatabase.Tags.Should().ContainSingle(workTag => workTag.Id == existingTags[0].Id); workItemInDatabase.Tags.Should().ContainSingle(workTag => workTag.Id == existingTags[1].Id); workItemInDatabase.Tags.Should().ContainSingle(workTag => workTag.Id == existingTags[2].Id); @@ -354,15 +354,15 @@ public async Task Cannot_create_for_missing_relationship_type() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/subscribers/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -399,15 +399,15 @@ public async Task Cannot_create_for_unknown_relationship_type() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/subscribers/data[0]/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -443,15 +443,15 @@ public async Task Cannot_create_for_missing_relationship_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/subscribers/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -461,7 +461,7 @@ public async Task Cannot_create_for_unknown_relationship_IDs() string workItemId1 = Unknown.StringId.For(); string workItemId2 = Unknown.StringId.AltFor(); - UserAccount newUserAccount = _fakers.UserAccount.Generate(); + UserAccount newUserAccount = _fakers.UserAccount.GenerateOne(); var requestBody = new { @@ -503,7 +503,7 @@ public async Task Cannot_create_for_unknown_relationship_IDs() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(2); + responseDocument.Errors.Should().HaveCount(2); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -552,22 +552,22 @@ public async Task Cannot_create_on_relationship_type_mismatch() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Incompatible resource type found."); error.Detail.Should().Be("Type 'rgbColors' is not convertible to type 'userAccounts' of relationship 'subscribers'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/subscribers/data[0]/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_create_with_duplicates() { // Arrange - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -610,21 +610,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldNotBeEmpty(); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().NotBeEmpty(); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("userAccounts"); responseDocument.Included[0].Id.Should().Be(existingUserAccount.StringId); - int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Subscribers).FirstWithIdAsync(newWorkItemId); - workItemInDatabase.Subscribers.ShouldHaveCount(1); + workItemInDatabase.Subscribers.Should().HaveCount(1); workItemInDatabase.Subscribers.Single().Id.Should().Be(existingUserAccount.Id); }); } @@ -655,15 +655,15 @@ public async Task Cannot_create_with_missing_data_in_OneToMany_relationship() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'data' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/subscribers"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -693,15 +693,15 @@ public async Task Cannot_create_with_null_data_in_ManyToMany_relationship() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an array, instead of 'null'."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/tags/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -733,15 +733,15 @@ public async Task Cannot_create_with_object_data_in_ManyToMany_relationship() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an array, instead of an object."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/tags/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -781,15 +781,15 @@ public async Task Cannot_create_resource_with_local_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'lid' element is not supported at this endpoint."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/lid"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -826,14 +826,14 @@ public async Task Cannot_assign_relationship_with_blocked_capability() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Relationship cannot be assigned."); error.Detail.Should().Be("The relationship 'items' on resource type 'workItemGroups' cannot be assigned to."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/items"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToOneRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToOneRelationshipTests.cs index 2aaf524543..42c63fd357 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToOneRelationshipTests.cs @@ -32,10 +32,10 @@ public CreateResourceWithToOneRelationshipTests(IntegrationTestContext { @@ -74,11 +74,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldNotBeEmpty(); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().NotBeEmpty(); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); - string newGroupId = responseDocument.Data.SingleValue.Id.ShouldNotBeNull(); + string newGroupId = responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -86,7 +86,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WorkItemGroup newGroupInDatabase = groupsInDatabase.Single(group => group.StringId == newGroupId); newGroupInDatabase.Name.Should().Be(newGroupName); - newGroupInDatabase.Color.ShouldNotBeNull(); + newGroupInDatabase.Color.Should().NotBeNull(); newGroupInDatabase.Color.Id.Should().Be(existingGroup.Color.Id); WorkItemGroup existingGroupInDatabase = groupsInDatabase.Single(group => group.Id == existingGroup.Id); @@ -98,11 +98,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToOne_relationship_from_dependent_side() { // Arrange - RgbColor existingColor = _fakers.RgbColor.Generate(); - existingColor.Group = _fakers.WorkItemGroup.Generate(); + RgbColor existingColor = _fakers.RgbColor.GenerateOne(); + existingColor.Group = _fakers.WorkItemGroup.GenerateOne(); const string newColorId = "0A0B0C"; - string newDisplayName = _fakers.RgbColor.Generate().DisplayName; + string newDisplayName = _fakers.RgbColor.GenerateOne().DisplayName; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -150,11 +150,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => RgbColor newColorInDatabase = colorsInDatabase.Single(color => color.Id == newColorId); newColorInDatabase.DisplayName.Should().Be(newDisplayName); - newColorInDatabase.Group.ShouldNotBeNull(); + newColorInDatabase.Group.Should().NotBeNull(); newColorInDatabase.Group.Id.Should().Be(existingColor.Group.Id); RgbColor? existingColorInDatabase = colorsInDatabase.SingleOrDefault(color => color.Id == existingColor.Id); - existingColorInDatabase.ShouldNotBeNull(); + existingColorInDatabase.Should().NotBeNull(); existingColorInDatabase.Group.Should().BeNull(); }); } @@ -163,7 +163,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_relationship_with_include() { // Arrange - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -198,24 +198,24 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldNotBeEmpty(); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().NotBeEmpty(); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("userAccounts"); responseDocument.Included[0].Id.Should().Be(existingUserAccount.StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("firstName").With(value => value.Should().Be(existingUserAccount.FirstName)); - responseDocument.Included[0].Attributes.ShouldContainKey("lastName").With(value => value.Should().Be(existingUserAccount.LastName)); - responseDocument.Included[0].Relationships.ShouldNotBeEmpty(); + responseDocument.Included[0].Attributes.Should().ContainKey("firstName").WhoseValue.Should().Be(existingUserAccount.FirstName); + responseDocument.Included[0].Attributes.Should().ContainKey("lastName").WhoseValue.Should().Be(existingUserAccount.LastName); + responseDocument.Included[0].Relationships.Should().NotBeEmpty(); - int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Assignee).FirstWithIdAsync(newWorkItemId); - workItemInDatabase.Assignee.ShouldNotBeNull(); + workItemInDatabase.Assignee.Should().NotBeNull(); workItemInDatabase.Assignee.Id.Should().Be(existingUserAccount.Id); }); } @@ -224,8 +224,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_relationship_with_include_and_primary_fieldset() { // Arrange - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); - WorkItem newWorkItem = _fakers.WorkItem.Generate(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); + WorkItem newWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -265,26 +265,26 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldHaveCount(1); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("description").With(value => value.Should().Be(newWorkItem.Description)); - responseDocument.Data.SingleValue.Relationships.ShouldHaveCount(1); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().HaveCount(1); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("description").WhoseValue.Should().Be(newWorkItem.Description); + responseDocument.Data.SingleValue.Relationships.Should().HaveCount(1); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("assignee").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("assignee").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.SingleValue.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Data.SingleValue.Should().NotBeNull(); value.Data.SingleValue.Id.Should().Be(existingUserAccount.StringId); }); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("userAccounts"); responseDocument.Included[0].Id.Should().Be(existingUserAccount.StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("firstName").With(value => value.Should().Be(existingUserAccount.FirstName)); - responseDocument.Included[0].Attributes.ShouldContainKey("lastName").With(value => value.Should().Be(existingUserAccount.LastName)); - responseDocument.Included[0].Relationships.ShouldNotBeEmpty(); + responseDocument.Included[0].Attributes.Should().ContainKey("firstName").WhoseValue.Should().Be(existingUserAccount.FirstName); + responseDocument.Included[0].Attributes.Should().ContainKey("lastName").WhoseValue.Should().Be(existingUserAccount.LastName); + responseDocument.Included[0].Relationships.Should().NotBeEmpty(); - int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -292,7 +292,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => workItemInDatabase.Description.Should().Be(newWorkItem.Description); workItemInDatabase.Priority.Should().Be(newWorkItem.Priority); - workItemInDatabase.Assignee.ShouldNotBeNull(); + workItemInDatabase.Assignee.Should().NotBeNull(); workItemInDatabase.Assignee.Id.Should().Be(existingUserAccount.Id); }); } @@ -301,7 +301,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_with_null_relationship() { // Arrange - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -329,22 +329,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object, instead of 'null'."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/assignee"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_with_missing_data_in_relationship() { // Arrange - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -374,22 +374,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'data' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/assignee"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_with_array_data_in_relationship() { // Arrange - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -427,15 +427,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object or 'null', instead of an array."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/assignee/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -468,15 +468,15 @@ public async Task Cannot_create_for_missing_relationship_type() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/assignee/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -510,15 +510,15 @@ public async Task Cannot_create_for_unknown_relationship_type() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/assignee/data/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -551,15 +551,15 @@ public async Task Cannot_create_for_missing_relationship_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/assignee/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -595,7 +595,7 @@ public async Task Cannot_create_with_unknown_relationship_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -636,22 +636,22 @@ public async Task Cannot_create_on_relationship_type_mismatch() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Incompatible resource type found."); error.Detail.Should().Be("Type 'rgbColors' is not convertible to type 'userAccounts' of relationship 'assignee'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/assignee/data/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_create_resource_with_duplicate_relationship() { // Arrange - List existingUserAccounts = _fakers.UserAccount.Generate(2); + List existingUserAccounts = _fakers.UserAccount.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -696,24 +696,24 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldNotBeEmpty(); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().NotBeEmpty(); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("userAccounts"); responseDocument.Included[0].Id.Should().Be(existingUserAccounts[1].StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("firstName").With(value => value.Should().Be(existingUserAccounts[1].FirstName)); - responseDocument.Included[0].Attributes.ShouldContainKey("lastName").With(value => value.Should().Be(existingUserAccounts[1].LastName)); - responseDocument.Included[0].Relationships.ShouldNotBeEmpty(); + responseDocument.Included[0].Attributes.Should().ContainKey("firstName").WhoseValue.Should().Be(existingUserAccounts[1].FirstName); + responseDocument.Included[0].Attributes.Should().ContainKey("lastName").WhoseValue.Should().Be(existingUserAccounts[1].LastName); + responseDocument.Included[0].Relationships.Should().NotBeEmpty(); - int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Assignee).FirstWithIdAsync(newWorkItemId); - workItemInDatabase.Assignee.ShouldNotBeNull(); + workItemInDatabase.Assignee.Should().NotBeNull(); workItemInDatabase.Assignee.Id.Should().Be(existingUserAccounts[1].Id); }); } @@ -752,15 +752,15 @@ public async Task Cannot_create_resource_with_local_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'lid' element is not supported at this endpoint."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/lid"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -794,14 +794,14 @@ public async Task Cannot_assign_relationship_with_blocked_capability() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Relationship cannot be assigned."); error.Detail.Should().Be("The relationship 'group' on resource type 'workItems' cannot be assigned to."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/group"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Deleting/DeleteResourceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Deleting/DeleteResourceTests.cs index 9fb79db38f..55f870e6d2 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Deleting/DeleteResourceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Deleting/DeleteResourceTests.cs @@ -25,7 +25,7 @@ public DeleteResourceTests(IntegrationTestContext { @@ -65,7 +65,7 @@ public async Task Cannot_delete_unknown_resource() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -79,8 +79,8 @@ public async Task Cannot_delete_unknown_resource() public async Task Can_delete_resource_with_OneToOne_relationship_from_dependent_side() { // Arrange - RgbColor existingColor = _fakers.RgbColor.Generate(); - existingColor.Group = _fakers.WorkItemGroup.Generate(); + RgbColor existingColor = _fakers.RgbColor.GenerateOne(); + existingColor.Group = _fakers.WorkItemGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -114,8 +114,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_existing_resource_with_OneToOne_relationship_from_principal_side() { // Arrange - WorkItemGroup existingGroup = _fakers.WorkItemGroup.Generate(); - existingGroup.Color = _fakers.RgbColor.Generate(); + WorkItemGroup existingGroup = _fakers.WorkItemGroup.GenerateOne(); + existingGroup.Color = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -141,7 +141,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => RgbColor? colorInDatabase = await dbContext.RgbColors.FirstWithIdOrDefaultAsync(existingGroup.Color.Id); - colorInDatabase.ShouldNotBeNull(); + colorInDatabase.Should().NotBeNull(); colorInDatabase.Group.Should().BeNull(); }); } @@ -150,8 +150,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_existing_resource_with_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(2).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -186,8 +186,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource_with_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Tags = _fakers.WorkTag.Generate(1).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Tags = _fakers.WorkTag.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -213,7 +213,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WorkTag? tagInDatabase = await dbContext.WorkTags.FirstWithIdOrDefaultAsync(existingWorkItem.Tags.ElementAt(0).Id); - tagInDatabase.ShouldNotBeNull(); + tagInDatabase.Should().NotBeNull(); }); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Fetching/FetchRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Fetching/FetchRelationshipTests.cs index 35ff4abcb0..96f3d9a439 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Fetching/FetchRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Fetching/FetchRelationshipTests.cs @@ -22,8 +22,8 @@ public FetchRelationshipTests(IntegrationTestContext { @@ -39,7 +39,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("userAccounts"); responseDocument.Data.SingleValue.Id.Should().Be(workItem.Assignee.StringId); responseDocument.Data.SingleValue.Attributes.Should().BeNull(); @@ -49,7 +49,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => [Fact] public async Task Can_get_empty_ManyToOne_relationship() { - WorkItem workItem = _fakers.WorkItem.Generate(); + WorkItem workItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -72,8 +72,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_OneToMany_relationship() { // Arrange - UserAccount userAccount = _fakers.UserAccount.Generate(); - userAccount.AssignedItems = _fakers.WorkItem.Generate(2).ToHashSet(); + UserAccount userAccount = _fakers.UserAccount.GenerateOne(); + userAccount.AssignedItems = _fakers.WorkItem.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -89,7 +89,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); ResourceObject item1 = responseDocument.Data.ManyValue.Single(resource => resource.Id == userAccount.AssignedItems.ElementAt(0).StringId); item1.Type.Should().Be("workItems"); @@ -106,7 +106,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_empty_OneToMany_relationship() { // Arrange - UserAccount userAccount = _fakers.UserAccount.Generate(); + UserAccount userAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -129,8 +129,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_ManyToMany_relationship() { // Arrange - WorkItem workItem = _fakers.WorkItem.Generate(); - workItem.Tags = _fakers.WorkTag.Generate(2).ToHashSet(); + WorkItem workItem = _fakers.WorkItem.GenerateOne(); + workItem.Tags = _fakers.WorkTag.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -146,7 +146,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); ResourceObject item1 = responseDocument.Data.ManyValue.Single(resource => resource.Id == workItem.Tags.ElementAt(0).StringId); item1.Type.Should().Be("workTags"); @@ -163,7 +163,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_empty_ManyToMany_relationship() { // Arrange - WorkItem workItem = _fakers.WorkItem.Generate(); + WorkItem workItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -209,7 +209,7 @@ public async Task Cannot_get_relationship_for_unknown_primary_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -220,7 +220,7 @@ public async Task Cannot_get_relationship_for_unknown_primary_ID() [Fact] public async Task Cannot_get_relationship_for_unknown_relationship_type() { - WorkItem workItem = _fakers.WorkItem.Generate(); + WorkItem workItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -236,11 +236,38 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); error.Title.Should().Be("The requested relationship does not exist."); error.Detail.Should().Be($"Resource of type 'workItems' does not contain a relationship named '{Unknown.Relationship}'."); } + + [Fact] + public async Task Cannot_get_relationship_for_whitespace_relationship_name() + { + WorkItem workItem = _fakers.WorkItem.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WorkItems.Add(workItem); + await dbContext.SaveChangesAsync(); + }); + + string route = $"/workItems/{workItem.StringId}/relationships/%20%20"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecuteGetAsync(route); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); + + responseDocument.Errors.Should().HaveCount(1); + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.NotFound); + error.Title.Should().Be("The requested relationship does not exist."); + error.Detail.Should().Be("Resource of type 'workItems' does not contain a relationship named ' '."); + } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Fetching/FetchResourceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Fetching/FetchResourceTests.cs index 221ab16ec7..77ec9acbbb 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Fetching/FetchResourceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Fetching/FetchResourceTests.cs @@ -24,7 +24,7 @@ public FetchResourceTests(IntegrationTestContext workItems = _fakers.WorkItem.Generate(2); + List workItems = _fakers.WorkItem.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -41,21 +41,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); ResourceObject item1 = responseDocument.Data.ManyValue.Single(resource => resource.Id == workItems[0].StringId); item1.Type.Should().Be("workItems"); - item1.Attributes.ShouldContainKey("description").With(value => value.Should().Be(workItems[0].Description)); - item1.Attributes.ShouldContainKey("dueAt").With(value => value.Should().Be(workItems[0].DueAt)); - item1.Attributes.ShouldContainKey("priority").With(value => value.Should().Be(workItems[0].Priority)); - item1.Relationships.ShouldNotBeEmpty(); + item1.Attributes.Should().ContainKey("description").WhoseValue.Should().Be(workItems[0].Description); + item1.Attributes.Should().ContainKey("dueAt").WhoseValue.Should().Be(workItems[0].DueAt); + item1.Attributes.Should().ContainKey("priority").WhoseValue.Should().Be(workItems[0].Priority); + item1.Relationships.Should().NotBeEmpty(); ResourceObject item2 = responseDocument.Data.ManyValue.Single(resource => resource.Id == workItems[1].StringId); item2.Type.Should().Be("workItems"); - item2.Attributes.ShouldContainKey("description").With(value => value.Should().Be(workItems[1].Description)); - item2.Attributes.ShouldContainKey("dueAt").With(value => value.Should().Be(workItems[1].DueAt)); - item2.Attributes.ShouldContainKey("priority").With(value => value.Should().Be(workItems[1].Priority)); - item2.Relationships.ShouldNotBeEmpty(); + item2.Attributes.Should().ContainKey("description").WhoseValue.Should().Be(workItems[1].Description); + item2.Attributes.Should().ContainKey("dueAt").WhoseValue.Should().Be(workItems[1].DueAt); + item2.Attributes.Should().ContainKey("priority").WhoseValue.Should().Be(workItems[1].Priority); + item2.Relationships.Should().NotBeEmpty(); } [Fact] @@ -77,7 +77,7 @@ public async Task Cannot_get_primary_resources_for_unknown_type() public async Task Can_get_primary_resource_by_ID() { // Arrange - WorkItem workItem = _fakers.WorkItem.Generate(); + WorkItem workItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -93,13 +93,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("workItems"); responseDocument.Data.SingleValue.Id.Should().Be(workItem.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("description").With(value => value.Should().Be(workItem.Description)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("dueAt").With(value => value.Should().Be(workItem.DueAt)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("priority").With(value => value.Should().Be(workItem.Priority)); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("description").WhoseValue.Should().Be(workItem.Description); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("dueAt").WhoseValue.Should().Be(workItem.DueAt); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("priority").WhoseValue.Should().Be(workItem.Priority); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); } [Fact] @@ -131,7 +131,7 @@ public async Task Cannot_get_primary_resource_for_unknown_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -143,8 +143,8 @@ public async Task Cannot_get_primary_resource_for_unknown_ID() public async Task Can_get_secondary_ManyToOne_resource() { // Arrange - WorkItem workItem = _fakers.WorkItem.Generate(); - workItem.Assignee = _fakers.UserAccount.Generate(); + WorkItem workItem = _fakers.WorkItem.GenerateOne(); + workItem.Assignee = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -160,19 +160,19 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("userAccounts"); responseDocument.Data.SingleValue.Id.Should().Be(workItem.Assignee.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("firstName").With(value => value.Should().Be(workItem.Assignee.FirstName)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("lastName").With(value => value.Should().Be(workItem.Assignee.LastName)); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("firstName").WhoseValue.Should().Be(workItem.Assignee.FirstName); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("lastName").WhoseValue.Should().Be(workItem.Assignee.LastName); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); } [Fact] public async Task Can_get_unknown_secondary_ManyToOne_resource() { // Arrange - WorkItem workItem = _fakers.WorkItem.Generate(); + WorkItem workItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -195,8 +195,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_secondary_OneToMany_resources() { // Arrange - UserAccount userAccount = _fakers.UserAccount.Generate(); - userAccount.AssignedItems = _fakers.WorkItem.Generate(2).ToHashSet(); + UserAccount userAccount = _fakers.UserAccount.GenerateOne(); + userAccount.AssignedItems = _fakers.WorkItem.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -212,28 +212,28 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); ResourceObject item1 = responseDocument.Data.ManyValue.Single(resource => resource.Id == userAccount.AssignedItems.ElementAt(0).StringId); item1.Type.Should().Be("workItems"); - item1.Attributes.ShouldContainKey("description").With(value => value.Should().Be(userAccount.AssignedItems.ElementAt(0).Description)); - item1.Attributes.ShouldContainKey("dueAt").With(value => value.Should().Be(userAccount.AssignedItems.ElementAt(0).DueAt)); - item1.Attributes.ShouldContainKey("priority").With(value => value.Should().Be(userAccount.AssignedItems.ElementAt(0).Priority)); - item1.Relationships.ShouldNotBeEmpty(); + item1.Attributes.Should().ContainKey("description").WhoseValue.Should().Be(userAccount.AssignedItems.ElementAt(0).Description); + item1.Attributes.Should().ContainKey("dueAt").WhoseValue.Should().Be(userAccount.AssignedItems.ElementAt(0).DueAt); + item1.Attributes.Should().ContainKey("priority").WhoseValue.Should().Be(userAccount.AssignedItems.ElementAt(0).Priority); + item1.Relationships.Should().NotBeEmpty(); ResourceObject item2 = responseDocument.Data.ManyValue.Single(resource => resource.Id == userAccount.AssignedItems.ElementAt(1).StringId); item2.Type.Should().Be("workItems"); - item2.Attributes.ShouldContainKey("description").With(value => value.Should().Be(userAccount.AssignedItems.ElementAt(1).Description)); - item2.Attributes.ShouldContainKey("dueAt").With(value => value.Should().Be(userAccount.AssignedItems.ElementAt(1).DueAt)); - item2.Attributes.ShouldContainKey("priority").With(value => value.Should().Be(userAccount.AssignedItems.ElementAt(1).Priority)); - item2.Relationships.ShouldNotBeEmpty(); + item2.Attributes.Should().ContainKey("description").WhoseValue.Should().Be(userAccount.AssignedItems.ElementAt(1).Description); + item2.Attributes.Should().ContainKey("dueAt").WhoseValue.Should().Be(userAccount.AssignedItems.ElementAt(1).DueAt); + item2.Attributes.Should().ContainKey("priority").WhoseValue.Should().Be(userAccount.AssignedItems.ElementAt(1).Priority); + item2.Relationships.Should().NotBeEmpty(); } [Fact] public async Task Can_get_unknown_secondary_OneToMany_resources() { // Arrange - UserAccount userAccount = _fakers.UserAccount.Generate(); + UserAccount userAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -256,8 +256,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_secondary_ManyToMany_resources() { // Arrange - WorkItem workItem = _fakers.WorkItem.Generate(); - workItem.Tags = _fakers.WorkTag.Generate(2).ToHashSet(); + WorkItem workItem = _fakers.WorkItem.GenerateOne(); + workItem.Tags = _fakers.WorkTag.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -273,26 +273,26 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); ResourceObject item1 = responseDocument.Data.ManyValue.Single(resource => resource.Id == workItem.Tags.ElementAt(0).StringId); item1.Type.Should().Be("workTags"); - item1.Attributes.ShouldContainKey("text").With(value => value.Should().Be(workItem.Tags.ElementAt(0).Text)); - item1.Attributes.ShouldContainKey("isBuiltIn").With(value => value.Should().Be(workItem.Tags.ElementAt(0).IsBuiltIn)); - item1.Relationships.ShouldNotBeEmpty(); + item1.Attributes.Should().ContainKey("text").WhoseValue.Should().Be(workItem.Tags.ElementAt(0).Text); + item1.Attributes.Should().ContainKey("isBuiltIn").WhoseValue.Should().Be(workItem.Tags.ElementAt(0).IsBuiltIn); + item1.Relationships.Should().NotBeEmpty(); ResourceObject item2 = responseDocument.Data.ManyValue.Single(resource => resource.Id == workItem.Tags.ElementAt(1).StringId); item2.Type.Should().Be("workTags"); - item2.Attributes.ShouldContainKey("text").With(value => value.Should().Be(workItem.Tags.ElementAt(1).Text)); - item2.Attributes.ShouldContainKey("isBuiltIn").With(value => value.Should().Be(workItem.Tags.ElementAt(1).IsBuiltIn)); - item2.Relationships.ShouldNotBeEmpty(); + item2.Attributes.Should().ContainKey("text").WhoseValue.Should().Be(workItem.Tags.ElementAt(1).Text); + item2.Attributes.Should().ContainKey("isBuiltIn").WhoseValue.Should().Be(workItem.Tags.ElementAt(1).IsBuiltIn); + item2.Relationships.Should().NotBeEmpty(); } [Fact] public async Task Can_get_unknown_secondary_ManyToMany_resources() { // Arrange - WorkItem workItem = _fakers.WorkItem.Generate(); + WorkItem workItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -340,7 +340,7 @@ public async Task Cannot_get_secondary_resource_for_unknown_primary_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -352,8 +352,8 @@ public async Task Cannot_get_secondary_resource_for_unknown_primary_ID() public async Task Cannot_get_secondary_resource_for_unknown_relationship() { // Arrange - WorkItem workItem = _fakers.WorkItem.Generate(); - workItem.Assignee = _fakers.UserAccount.Generate(); + WorkItem workItem = _fakers.WorkItem.GenerateOne(); + workItem.Assignee = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -369,11 +369,39 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); error.Title.Should().Be("The requested relationship does not exist."); error.Detail.Should().Be($"Resource of type 'workItems' does not contain a relationship named '{Unknown.Relationship}'."); } + + [Fact] + public async Task Cannot_get_secondary_resource_for_whitespace_relationship_name() + { + // Arrange + WorkItem workItem = _fakers.WorkItem.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WorkItems.Add(workItem); + await dbContext.SaveChangesAsync(); + }); + + string route = $"/workItems/{workItem.StringId}/%20"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecuteGetAsync(route); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); + + responseDocument.Errors.Should().HaveCount(1); + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.NotFound); + error.Title.Should().Be("The requested relationship does not exist."); + error.Detail.Should().Be("Resource of type 'workItems' does not contain a relationship named ' '."); + } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/ReadWriteDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/ReadWriteDbContext.cs index e8350555d5..b76f018448 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/ReadWriteDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/ReadWriteDbContext.cs @@ -8,7 +8,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ReadWrite; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class ReadWriteDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class ReadWriteDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet WorkItems => Set(); public DbSet WorkTags => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/RgbColor.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/RgbColor.cs index 05af73148f..28762384c9 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/RgbColor.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/RgbColor.cs @@ -6,7 +6,7 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ReadWrite; [UsedImplicitly(ImplicitUseTargetFlags.Members)] [Resource(ControllerNamespace = "JsonApiDotNetCoreTests.IntegrationTests.ReadWrite")] -public sealed class RgbColor : Identifiable +public sealed class RgbColor : Identifiable { [Attr] public string DisplayName { get; set; } = null!; diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/AddToToManyRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/AddToToManyRelationshipTests.cs index acf46913a0..2da2983765 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/AddToToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/AddToToManyRelationshipTests.cs @@ -25,8 +25,8 @@ public AddToToManyRelationshipTests(IntegrationTestContext { @@ -51,24 +51,24 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); error.Title.Should().Be("Failed to deserialize request body: Only to-many relationships can be targeted through this endpoint."); error.Detail.Should().Be("Relationship 'assignee' is not a to-many relationship."); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_add_to_OneToMany_relationship_with_already_assigned_resources() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(2).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(2); - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -107,7 +107,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Subscribers).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Subscribers.ShouldHaveCount(3); + workItemInDatabase.Subscribers.Should().HaveCount(3); workItemInDatabase.Subscribers.Should().ContainSingle(subscriber => subscriber.Id == existingWorkItem.Subscribers.ElementAt(0).Id); workItemInDatabase.Subscribers.Should().ContainSingle(subscriber => subscriber.Id == existingWorkItem.Subscribers.ElementAt(1).Id); workItemInDatabase.Subscribers.Should().ContainSingle(subscriber => subscriber.Id == existingSubscriber.Id); @@ -118,9 +118,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_to_ManyToMany_relationship_with_already_assigned_resources() { // Arrange - List existingWorkItems = _fakers.WorkItem.Generate(2); - existingWorkItems[0].Tags = _fakers.WorkTag.Generate(1).ToHashSet(); - existingWorkItems[1].Tags = _fakers.WorkTag.Generate(1).ToHashSet(); + List existingWorkItems = _fakers.WorkItem.GenerateList(2); + existingWorkItems[0].Tags = _fakers.WorkTag.GenerateSet(1); + existingWorkItems[1].Tags = _fakers.WorkTag.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -164,13 +164,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => int tagId1 = existingWorkItems[0].Tags.ElementAt(0).Id; int tagId2 = existingWorkItems[1].Tags.ElementAt(0).Id; - workItemInDatabase1.Tags.ShouldHaveCount(2); + workItemInDatabase1.Tags.Should().HaveCount(2); workItemInDatabase1.Tags.Should().ContainSingle(workTag => workTag.Id == tagId1); workItemInDatabase1.Tags.Should().ContainSingle(workTag => workTag.Id == tagId2); WorkItem workItemInDatabase2 = workItemsInDatabase.Single(workItem => workItem.Id == existingWorkItems[1].Id); - workItemInDatabase2.Tags.ShouldHaveCount(1); + workItemInDatabase2.Tags.Should().HaveCount(1); workItemInDatabase2.Tags.ElementAt(0).Id.Should().Be(tagId2); }); } @@ -179,7 +179,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_for_missing_request_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -197,10 +197,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - httpResponse.Content.Headers.ContentType.ShouldNotBeNull(); - httpResponse.Content.Headers.ContentType.ToString().Should().Be(HeaderConstants.MediaType); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); @@ -214,7 +214,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_for_null_request_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -232,21 +232,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object, instead of 'null'."); error.Detail.Should().BeNull(); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_add_for_missing_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -273,22 +273,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_add_for_unknown_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -316,22 +316,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data[0]/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_add_for_missing_ID() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -358,22 +358,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_add_unknown_IDs_to_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -409,7 +409,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(2); + responseDocument.Errors.Should().HaveCount(2); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -428,7 +428,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_unknown_IDs_to_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -464,7 +464,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(2); + responseDocument.Errors.Should().HaveCount(2); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -483,8 +483,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_to_unknown_resource_type_in_url() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -519,7 +519,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_to_unknown_resource_ID_in_url() { // Arrange - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -549,7 +549,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -563,7 +563,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_to_unknown_relationship_in_url() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -591,7 +591,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -601,12 +601,54 @@ await _testContext.RunOnDatabaseAsync(async dbContext => error.Meta.Should().NotContainKey("requestBody"); } + [Fact] + public async Task Cannot_add_to_whitespace_relationship_in_url() + { + // Arrange + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WorkItems.Add(existingWorkItem); + await dbContext.SaveChangesAsync(); + }); + + var requestBody = new + { + data = new[] + { + new + { + type = "userAccounts", + id = Unknown.StringId.For() + } + } + }; + + string route = $"/workItems/{existingWorkItem.StringId}/relationships/%20%20"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); + + responseDocument.Errors.Should().HaveCount(1); + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.NotFound); + error.Title.Should().Be("The requested relationship does not exist."); + error.Detail.Should().Be("Resource of type 'workItems' does not contain a relationship named ' '."); + error.Source.Should().BeNull(); + error.Meta.Should().NotContainKey("requestBody"); + } + [Fact] public async Task Cannot_add_for_relationship_mismatch_between_url_and_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -634,23 +676,23 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Incompatible resource type found."); error.Detail.Should().Be("Type 'userAccounts' is not convertible to type 'workTags' of relationship 'tags'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data[0]/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_add_with_duplicates() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -689,7 +731,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Subscribers).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Subscribers.ShouldHaveCount(1); + workItemInDatabase.Subscribers.Should().HaveCount(1); workItemInDatabase.Subscribers.Single().Id.Should().Be(existingSubscriber.Id); }); } @@ -698,7 +740,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_with_empty_list() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -725,7 +767,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Subscribers).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Subscribers.ShouldHaveCount(0); + workItemInDatabase.Subscribers.Should().HaveCount(0); }); } @@ -733,7 +775,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_with_missing_data_in_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -753,21 +795,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'data' element is required."); error.Detail.Should().BeNull(); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_add_with_null_data_in_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -788,22 +830,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an array, instead of 'null'."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_add_with_object_data_in_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -826,23 +868,23 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an array, instead of an object."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_add_self_to_cyclic_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Children = _fakers.WorkItem.Generate(1); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Children = _fakers.WorkItem.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -876,7 +918,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Children).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Children.ShouldHaveCount(2); + workItemInDatabase.Children.Should().HaveCount(2); workItemInDatabase.Children.Should().ContainSingle(workItem => workItem.Id == existingWorkItem.Children[0].Id); workItemInDatabase.Children.Should().ContainSingle(workItem => workItem.Id == existingWorkItem.Id); }); @@ -886,8 +928,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_self_to_cyclic_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.RelatedTo = _fakers.WorkItem.Generate(1); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.RelatedTo = _fakers.WorkItem.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -930,10 +972,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // @formatter:wrap_after_property_in_chained_method_calls restore // @formatter:wrap_chained_method_calls restore - workItemInDatabase.RelatedFrom.ShouldHaveCount(1); + workItemInDatabase.RelatedFrom.Should().HaveCount(1); workItemInDatabase.RelatedFrom.Should().OnlyContain(workItem => workItem.Id == existingWorkItem.Id); - workItemInDatabase.RelatedTo.ShouldHaveCount(2); + workItemInDatabase.RelatedTo.Should().HaveCount(2); workItemInDatabase.RelatedTo.Should().ContainSingle(workItem => workItem.Id == existingWorkItem.Id); workItemInDatabase.RelatedTo.Should().ContainSingle(workItem => workItem.Id == existingWorkItem.RelatedTo[0].Id); }); @@ -943,7 +985,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_with_blocked_capability() { // Arrange - WorkItemGroup existingWorkItemGroup = _fakers.WorkItemGroup.Generate(); + WorkItemGroup existingWorkItemGroup = _fakers.WorkItemGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -971,13 +1013,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Relationship cannot be added to."); error.Detail.Should().Be("The relationship 'items' on resource type 'workItemGroups' cannot be added to."); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/RemoveFromToManyRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/RemoveFromToManyRelationshipTests.cs index 8df5e10a60..c8499bb95e 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/RemoveFromToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/RemoveFromToManyRelationshipTests.cs @@ -36,8 +36,8 @@ public RemoveFromToManyRelationshipTests(IntegrationTestContext { @@ -62,23 +62,23 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); error.Title.Should().Be("Failed to deserialize request body: Only to-many relationships can be targeted through this endpoint."); error.Detail.Should().Be("Relationship 'assignee' is not a to-many relationship."); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_remove_from_OneToMany_relationship_with_unassigned_existing_resource() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(2).ToHashSet(); - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(2); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -118,11 +118,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Subscribers).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Subscribers.ShouldHaveCount(1); + workItemInDatabase.Subscribers.Should().HaveCount(1); workItemInDatabase.Subscribers.Single().Id.Should().Be(existingWorkItem.Subscribers.ElementAt(1).Id); List userAccountsInDatabase = await dbContext.UserAccounts.ToListAsync(); - userAccountsInDatabase.ShouldHaveCount(3); + userAccountsInDatabase.Should().HaveCount(3); }); } @@ -130,8 +130,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_OneToMany_relationship_with_extra_removals_from_resource_definition() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(3).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -165,17 +165,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Should().BeEmpty(); - workItemDefinition.PreloadedSubscribers.ShouldHaveCount(1); + workItemDefinition.PreloadedSubscribers.Should().HaveCount(1); await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Subscribers).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Subscribers.ShouldHaveCount(1); + workItemInDatabase.Subscribers.Should().HaveCount(1); workItemInDatabase.Subscribers.Single().Id.Should().Be(existingWorkItem.Subscribers.ElementAt(1).Id); List userAccountsInDatabase = await dbContext.UserAccounts.ToListAsync(); - userAccountsInDatabase.ShouldHaveCount(3); + userAccountsInDatabase.Should().HaveCount(3); }); } @@ -183,10 +183,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_ManyToMany_relationship_with_unassigned_existing_resource() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Tags = _fakers.WorkTag.Generate(2).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Tags = _fakers.WorkTag.GenerateSet(2); - WorkTag existingTag = _fakers.WorkTag.Generate(); + WorkTag existingTag = _fakers.WorkTag.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -226,11 +226,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Tags).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Tags.ShouldHaveCount(1); + workItemInDatabase.Tags.Should().HaveCount(1); workItemInDatabase.Tags.Single().Id.Should().Be(existingWorkItem.Tags.ElementAt(0).Id); List tagsInDatabase = await dbContext.WorkTags.ToListAsync(); - tagsInDatabase.ShouldHaveCount(3); + tagsInDatabase.Should().HaveCount(3); }); } @@ -238,8 +238,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_ManyToMany_relationship_with_extra_removals_from_resource_definition() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Tags = _fakers.WorkTag.Generate(3).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Tags = _fakers.WorkTag.GenerateSet(3); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -273,17 +273,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Should().BeEmpty(); - workItemDefinition.PreloadedTags.ShouldHaveCount(1); + workItemDefinition.PreloadedTags.Should().HaveCount(1); await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Tags).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Tags.ShouldHaveCount(1); + workItemInDatabase.Tags.Should().HaveCount(1); workItemInDatabase.Tags.Single().Id.Should().Be(existingWorkItem.Tags.ElementAt(0).Id); List tagsInDatabase = await dbContext.WorkTags.ToListAsync(); - tagsInDatabase.ShouldHaveCount(3); + tagsInDatabase.Should().HaveCount(3); }); } @@ -291,7 +291,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_for_missing_request_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -309,10 +309,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - httpResponse.Content.Headers.ContentType.ShouldNotBeNull(); - httpResponse.Content.Headers.ContentType.ToString().Should().Be(HeaderConstants.MediaType); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); @@ -326,7 +326,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_for_null_request_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -344,22 +344,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object, instead of 'null'."); error.Detail.Should().BeNull(); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_remove_for_missing_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(1).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -386,22 +386,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_remove_for_unknown_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -429,22 +429,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data[0]/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_remove_for_missing_ID() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -471,22 +471,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_remove_unknown_IDs_from_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -522,7 +522,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(2); + responseDocument.Errors.Should().HaveCount(2); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -541,7 +541,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_unknown_IDs_from_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -577,7 +577,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(2); + responseDocument.Errors.Should().HaveCount(2); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -596,8 +596,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_from_unknown_resource_type_in_url() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(1).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -632,7 +632,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_from_unknown_resource_ID_in_url() { // Arrange - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -662,7 +662,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -676,7 +676,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_from_unknown_relationship_in_url() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -704,7 +704,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -714,12 +714,54 @@ await _testContext.RunOnDatabaseAsync(async dbContext => error.Meta.Should().NotContainKey("requestBody"); } + [Fact] + public async Task Cannot_remove_from_whitespace_relationship_in_url() + { + // Arrange + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WorkItems.Add(existingWorkItem); + await dbContext.SaveChangesAsync(); + }); + + var requestBody = new + { + data = new[] + { + new + { + type = "userAccounts", + id = Unknown.StringId.For() + } + } + }; + + string route = $"/workItems/{existingWorkItem.StringId}/relationships/%20"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecuteDeleteAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); + + responseDocument.Errors.Should().HaveCount(1); + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.NotFound); + error.Title.Should().Be("The requested relationship does not exist."); + error.Detail.Should().Be("Resource of type 'workItems' does not contain a relationship named ' '."); + error.Source.Should().BeNull(); + error.Meta.Should().NotContainKey("requestBody"); + } + [Fact] public async Task Cannot_remove_for_relationship_mismatch_between_url_and_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(1).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -747,23 +789,23 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Incompatible resource type found."); error.Detail.Should().Be("Type 'userAccounts' is not convertible to type 'workTags' of relationship 'tags'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data[0]/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_remove_with_duplicates() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(2).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -802,7 +844,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Subscribers).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Subscribers.ShouldHaveCount(1); + workItemInDatabase.Subscribers.Should().HaveCount(1); workItemInDatabase.Subscribers.Single().Id.Should().Be(existingWorkItem.Subscribers.ElementAt(1).Id); }); } @@ -811,8 +853,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_with_empty_list() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(1).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -839,7 +881,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Subscribers).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Subscribers.ShouldHaveCount(1); + workItemInDatabase.Subscribers.Should().HaveCount(1); workItemInDatabase.Subscribers.Single().Id.Should().Be(existingWorkItem.Subscribers.ElementAt(0).Id); }); } @@ -848,7 +890,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_with_missing_data_in_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -868,21 +910,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'data' element is required."); error.Detail.Should().BeNull(); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_remove_with_null_data_in_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -903,22 +945,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an array, instead of 'null'."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_remove_with_object_data_in_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -941,23 +983,23 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an array, instead of an object."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_remove_self_from_cyclic_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Children = _fakers.WorkItem.Generate(1); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Children = _fakers.WorkItem.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -994,7 +1036,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Children).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Children.ShouldHaveCount(1); + workItemInDatabase.Children.Should().HaveCount(1); workItemInDatabase.Children[0].Id.Should().Be(existingWorkItem.Children[0].Id); }); } @@ -1003,8 +1045,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_self_from_cyclic_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.RelatedFrom = _fakers.WorkItem.Generate(1); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.RelatedFrom = _fakers.WorkItem.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1050,7 +1092,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // @formatter:wrap_after_property_in_chained_method_calls restore // @formatter:wrap_chained_method_calls restore - workItemInDatabase.RelatedFrom.ShouldHaveCount(1); + workItemInDatabase.RelatedFrom.Should().HaveCount(1); workItemInDatabase.RelatedFrom[0].Id.Should().Be(existingWorkItem.RelatedFrom[0].Id); workItemInDatabase.RelatedTo.Should().BeEmpty(); @@ -1061,7 +1103,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_with_blocked_capability() { // Arrange - WorkItemGroup existingWorkItemGroup = _fakers.WorkItemGroup.Generate(); + WorkItemGroup existingWorkItemGroup = _fakers.WorkItemGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1089,26 +1131,27 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Relationship cannot be removed from."); error.Detail.Should().Be("The relationship 'items' on resource type 'workItemGroups' cannot be removed from."); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] - private sealed class RemoveExtraFromWorkItemDefinition(IResourceGraph resourceGraph) : JsonApiResourceDefinition(resourceGraph) + private sealed class RemoveExtraFromWorkItemDefinition(IResourceGraph resourceGraph) + : JsonApiResourceDefinition(resourceGraph) { // Enables to verify that not the full relationship was loaded upfront. - public ISet PreloadedSubscribers { get; } = new HashSet(IdentifiableComparer.Instance); - public ISet PreloadedTags { get; } = new HashSet(IdentifiableComparer.Instance); + public HashSet PreloadedSubscribers { get; } = new(IdentifiableComparer.Instance); + public HashSet PreloadedTags { get; } = new(IdentifiableComparer.Instance); // Enables to verify that adding extra IDs for removal from ResourceDefinition works correctly. - public ISet ExtraSubscribersIdsToRemove { get; } = new HashSet(); - public ISet ExtraTagIdsToRemove { get; } = new HashSet(); + public HashSet ExtraSubscribersIdsToRemove { get; } = []; + public HashSet ExtraTagIdsToRemove { get; } = []; public void Reset() { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/ReplaceToManyRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/ReplaceToManyRelationshipTests.cs index 48c25db786..5f4836cf24 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/ReplaceToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/ReplaceToManyRelationshipTests.cs @@ -25,8 +25,8 @@ public ReplaceToManyRelationshipTests(IntegrationTestContext { @@ -61,8 +61,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Tags = _fakers.WorkTag.Generate(1).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Tags = _fakers.WorkTag.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -97,10 +97,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToMany_relationship_with_already_assigned_resources() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(2).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(2); - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -139,7 +139,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Subscribers).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Subscribers.ShouldHaveCount(2); + workItemInDatabase.Subscribers.Should().HaveCount(2); workItemInDatabase.Subscribers.Should().ContainSingle(userAccount => userAccount.Id == existingWorkItem.Subscribers.ElementAt(1).Id); workItemInDatabase.Subscribers.Should().ContainSingle(userAccount => userAccount.Id == existingSubscriber.Id); }); @@ -149,10 +149,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ManyToMany_relationship_with_already_assigned_resources() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Tags = _fakers.WorkTag.Generate(2).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Tags = _fakers.WorkTag.GenerateSet(2); - List existingTags = _fakers.WorkTag.Generate(2); + List existingTags = _fakers.WorkTag.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -197,7 +197,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Tags).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Tags.ShouldHaveCount(3); + workItemInDatabase.Tags.Should().HaveCount(3); workItemInDatabase.Tags.Should().ContainSingle(workTag => workTag.Id == existingWorkItem.Tags.ElementAt(0).Id); workItemInDatabase.Tags.Should().ContainSingle(workTag => workTag.Id == existingTags[0].Id); workItemInDatabase.Tags.Should().ContainSingle(workTag => workTag.Id == existingTags[1].Id); @@ -208,7 +208,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_missing_request_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -226,10 +226,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - httpResponse.Content.Headers.ContentType.ShouldNotBeNull(); - httpResponse.Content.Headers.ContentType.ToString().Should().Be(HeaderConstants.MediaType); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); @@ -243,7 +243,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_null_request_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -261,21 +261,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object, instead of 'null'."); error.Detail.Should().BeNull(); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_replace_for_missing_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -302,22 +302,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_replace_for_unknown_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -345,22 +345,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data[0]/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_replace_for_missing_ID() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -387,22 +387,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_replace_with_unknown_IDs_in_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -438,7 +438,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(2); + responseDocument.Errors.Should().HaveCount(2); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -459,7 +459,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_with_unknown_IDs_in_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -495,7 +495,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(2); + responseDocument.Errors.Should().HaveCount(2); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -516,8 +516,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_on_unknown_resource_type_in_url() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -552,7 +552,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_on_unknown_resource_ID_in_url() { // Arrange - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -575,7 +575,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -589,7 +589,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_on_unknown_relationship_in_url() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -617,7 +617,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -627,12 +627,54 @@ await _testContext.RunOnDatabaseAsync(async dbContext => error.Meta.Should().NotContainKey("requestBody"); } + [Fact] + public async Task Cannot_replace_on_whitespace_relationship_in_url() + { + // Arrange + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WorkItems.Add(existingWorkItem); + await dbContext.SaveChangesAsync(); + }); + + var requestBody = new + { + data = new[] + { + new + { + type = "userAccounts", + id = Unknown.StringId.For() + } + } + }; + + string route = $"/workItems/{existingWorkItem.StringId}/relationships/%20%20"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePatchAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); + + responseDocument.Errors.Should().HaveCount(1); + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.NotFound); + error.Title.Should().Be("The requested relationship does not exist."); + error.Detail.Should().Be("Resource of type 'workItems' does not contain a relationship named ' '."); + error.Source.Should().BeNull(); + error.Meta.Should().NotContainKey("requestBody"); + } + [Fact] public async Task Cannot_replace_on_relationship_mismatch_between_url_and_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -660,25 +702,25 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Incompatible resource type found."); error.Detail.Should().Be("Type 'userAccounts' is not convertible to type 'workTags' of relationship 'tags'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data[0]/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_replace_with_duplicates() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(1).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(1); - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -717,7 +759,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Subscribers).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Subscribers.ShouldHaveCount(1); + workItemInDatabase.Subscribers.Should().HaveCount(1); workItemInDatabase.Subscribers.Single().Id.Should().Be(existingSubscriber.Id); }); } @@ -726,7 +768,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_with_missing_data_in_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -746,21 +788,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'data' element is required."); error.Detail.Should().BeNull(); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_replace_with_null_data_in_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -781,22 +823,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an array, instead of 'null'."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_replace_with_object_data_in_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -819,22 +861,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an array, instead of an object."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_clear_cyclic_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -876,7 +918,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_cyclic_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -924,7 +966,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_assign_cyclic_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -958,7 +1000,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Children).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Children.ShouldHaveCount(1); + workItemInDatabase.Children.Should().HaveCount(1); workItemInDatabase.Children[0].Id.Should().Be(existingWorkItem.Id); }); } @@ -967,7 +1009,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_assign_cyclic_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1010,10 +1052,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // @formatter:wrap_after_property_in_chained_method_calls restore // @formatter:wrap_chained_method_calls restore - workItemInDatabase.RelatedFrom.ShouldHaveCount(1); + workItemInDatabase.RelatedFrom.Should().HaveCount(1); workItemInDatabase.RelatedFrom[0].Id.Should().Be(existingWorkItem.Id); - workItemInDatabase.RelatedTo.ShouldHaveCount(1); + workItemInDatabase.RelatedTo.Should().HaveCount(1); workItemInDatabase.RelatedTo[0].Id.Should().Be(existingWorkItem.Id); }); } @@ -1022,7 +1064,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_assign_relationship_with_blocked_capability() { // Arrange - WorkItemGroup existingWorkItemGroup = _fakers.WorkItemGroup.Generate(); + WorkItemGroup existingWorkItemGroup = _fakers.WorkItemGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1050,13 +1092,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Relationship cannot be assigned."); error.Detail.Should().Be("The relationship 'items' on resource type 'workItemGroups' cannot be assigned to."); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/UpdateToOneRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/UpdateToOneRelationshipTests.cs index b85e268163..bff2522997 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/UpdateToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/UpdateToOneRelationshipTests.cs @@ -26,8 +26,8 @@ public UpdateToOneRelationshipTests(IntegrationTestContext { @@ -62,8 +62,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_OneToOne_relationship() { // Arrange - WorkItemGroup existingGroup = _fakers.WorkItemGroup.Generate(); - existingGroup.Color = _fakers.RgbColor.Generate(); + WorkItemGroup existingGroup = _fakers.WorkItemGroup.GenerateOne(); + existingGroup.Color = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -98,10 +98,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToOne_relationship_from_dependent_side() { // Arrange - WorkItemGroup existingGroup = _fakers.WorkItemGroup.Generate(); - existingGroup.Color = _fakers.RgbColor.Generate(); + WorkItemGroup existingGroup = _fakers.WorkItemGroup.GenerateOne(); + existingGroup.Color = _fakers.RgbColor.GenerateOne(); - RgbColor existingColor = _fakers.RgbColor.Generate(); + RgbColor existingColor = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -136,7 +136,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => colorInDatabase1.Group.Should().BeNull(); RgbColor colorInDatabase2 = colorsInDatabase.Single(color => color.Id == existingColor.Id); - colorInDatabase2.Group.ShouldNotBeNull(); + colorInDatabase2.Group.Should().NotBeNull(); colorInDatabase2.Group.Id.Should().Be(existingGroup.Id); }); } @@ -145,9 +145,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToOne_relationship_from_principal_side() { // Arrange - List existingGroups = _fakers.WorkItemGroup.Generate(2); - existingGroups[0].Color = _fakers.RgbColor.Generate(); - existingGroups[1].Color = _fakers.RgbColor.Generate(); + List existingGroups = _fakers.WorkItemGroup.GenerateList(2); + existingGroups[0].Color = _fakers.RgbColor.GenerateOne(); + existingGroups[1].Color = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -182,17 +182,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => groupInDatabase1.Color.Should().BeNull(); WorkItemGroup groupInDatabase2 = groupsInDatabase.Single(group => group.Id == existingGroups[1].Id); - groupInDatabase2.Color.ShouldNotBeNull(); + groupInDatabase2.Color.Should().NotBeNull(); groupInDatabase2.Color.Id.Should().Be(existingGroups[0].Color!.Id); List colorsInDatabase = await dbContext.RgbColors.Include(color => color.Group).ToListAsync(); RgbColor colorInDatabase1 = colorsInDatabase.Single(color => color.Id == existingGroups[0].Color!.Id); - colorInDatabase1.Group.ShouldNotBeNull(); + colorInDatabase1.Group.Should().NotBeNull(); colorInDatabase1.Group.Id.Should().Be(existingGroups[1].Id); RgbColor? colorInDatabase2 = colorsInDatabase.SingleOrDefault(color => color.Id == existingGroups[1].Color!.Id); - colorInDatabase2.ShouldNotBeNull(); + colorInDatabase2.Should().NotBeNull(); colorInDatabase2.Group.Should().BeNull(); }); } @@ -201,8 +201,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ManyToOne_relationship() { // Arrange - List existingUserAccounts = _fakers.UserAccount.Generate(2); - existingUserAccounts[0].AssignedItems = _fakers.WorkItem.Generate(2).ToHashSet(); + List existingUserAccounts = _fakers.UserAccount.GenerateList(2); + existingUserAccounts[0].AssignedItems = _fakers.WorkItem.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -235,7 +235,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WorkItem workItemInDatabase2 = await dbContext.WorkItems.Include(workItem => workItem.Assignee).FirstWithIdAsync(workItemId); - workItemInDatabase2.Assignee.ShouldNotBeNull(); + workItemInDatabase2.Assignee.Should().NotBeNull(); workItemInDatabase2.Assignee.Id.Should().Be(existingUserAccounts[1].Id); }); } @@ -244,7 +244,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_missing_request_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -262,10 +262,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - httpResponse.Content.Headers.ContentType.ShouldNotBeNull(); - httpResponse.Content.Headers.ContentType.ToString().Should().Be(HeaderConstants.MediaType); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); @@ -279,7 +279,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_null_request_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -297,22 +297,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object, instead of 'null'."); error.Detail.Should().BeNull(); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_for_missing_data() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -332,22 +332,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'data' element is required."); error.Detail.Should().BeNull(); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_for_array_data() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -375,22 +375,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object or 'null', instead of an array."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_for_missing_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -414,22 +414,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_for_unknown_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -454,22 +454,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_for_missing_ID() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -493,22 +493,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_with_unknown_ID() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -535,7 +535,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -549,8 +549,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_on_unknown_resource_type_in_url() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -582,7 +582,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_on_unknown_resource_ID_in_url() { // Arrange - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -609,7 +609,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -623,7 +623,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_on_unknown_relationship_in_url() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -648,7 +648,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -658,12 +658,51 @@ await _testContext.RunOnDatabaseAsync(async dbContext => error.Meta.Should().NotContainKey("requestBody"); } + [Fact] + public async Task Cannot_create_on_whitespace_relationship_in_url() + { + // Arrange + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WorkItems.Add(existingWorkItem); + await dbContext.SaveChangesAsync(); + }); + + var requestBody = new + { + data = new + { + type = "userAccounts", + id = Unknown.StringId.For() + } + }; + + string route = $"/workItems/{existingWorkItem.StringId}/relationships/%20"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePatchAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); + + responseDocument.Errors.Should().HaveCount(1); + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.NotFound); + error.Title.Should().Be("The requested relationship does not exist."); + error.Detail.Should().Be("Resource of type 'workItems' does not contain a relationship named ' '."); + error.Source.Should().BeNull(); + error.Meta.Should().NotContainKey("requestBody"); + } + [Fact] public async Task Cannot_create_on_relationship_mismatch_between_url_and_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - RgbColor existingColor = _fakers.RgbColor.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + RgbColor existingColor = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -688,22 +727,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Incompatible resource type found."); error.Detail.Should().Be("Type 'rgbColors' is not convertible to type 'userAccounts' of relationship 'assignee'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_clear_cyclic_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -741,7 +780,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_assign_cyclic_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -773,7 +812,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Parent).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Parent.ShouldNotBeNull(); + workItemInDatabase.Parent.Should().NotBeNull(); workItemInDatabase.Parent.Id.Should().Be(existingWorkItem.Id); }); } @@ -782,7 +821,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_assign_relationship_with_blocked_capability() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -807,13 +846,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Relationship cannot be assigned."); error.Detail.Should().Be("The relationship 'group' on resource type 'workItems' cannot be assigned to."); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/ReplaceToManyRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/ReplaceToManyRelationshipTests.cs index 32560b2ad9..f8317f14ec 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/ReplaceToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/ReplaceToManyRelationshipTests.cs @@ -28,8 +28,8 @@ public ReplaceToManyRelationshipTests(IntegrationTestContext { @@ -61,7 +61,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -75,8 +75,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Tags = _fakers.WorkTag.Generate(1).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Tags = _fakers.WorkTag.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -108,7 +108,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -122,10 +122,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToMany_relationship_with_already_assigned_resources() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(2).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(2); - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -169,13 +169,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Subscribers).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Subscribers.ShouldHaveCount(2); + workItemInDatabase.Subscribers.Should().HaveCount(2); workItemInDatabase.Subscribers.Should().ContainSingle(userAccount => userAccount.Id == existingWorkItem.Subscribers.ElementAt(1).Id); workItemInDatabase.Subscribers.Should().ContainSingle(userAccount => userAccount.Id == existingSubscriber.Id); }); @@ -185,10 +185,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ManyToMany_relationship_with_already_assigned_resources() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Tags = _fakers.WorkTag.Generate(2).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Tags = _fakers.WorkTag.GenerateSet(2); - List existingTags = _fakers.WorkTag.Generate(2); + List existingTags = _fakers.WorkTag.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -238,13 +238,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Tags).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Tags.ShouldHaveCount(3); + workItemInDatabase.Tags.Should().HaveCount(3); workItemInDatabase.Tags.Should().ContainSingle(workTag => workTag.Id == existingWorkItem.Tags.ElementAt(0).Id); workItemInDatabase.Tags.Should().ContainSingle(workTag => workTag.Id == existingTags[0].Id); workItemInDatabase.Tags.Should().ContainSingle(workTag => workTag.Id == existingTags[1].Id); @@ -255,8 +255,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToMany_relationship_with_include() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -295,24 +295,24 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("workItems"); responseDocument.Data.SingleValue.Id.Should().Be(existingWorkItem.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("priority").With(value => value.Should().Be(existingWorkItem.Priority)); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("priority").WhoseValue.Should().Be(existingWorkItem.Priority); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("userAccounts"); responseDocument.Included[0].Id.Should().Be(existingUserAccount.StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("firstName").With(value => value.Should().Be(existingUserAccount.FirstName)); - responseDocument.Included[0].Attributes.ShouldContainKey("lastName").With(value => value.Should().Be(existingUserAccount.LastName)); - responseDocument.Included[0].Relationships.ShouldNotBeEmpty(); + responseDocument.Included[0].Attributes.Should().ContainKey("firstName").WhoseValue.Should().Be(existingUserAccount.FirstName); + responseDocument.Included[0].Attributes.Should().ContainKey("lastName").WhoseValue.Should().Be(existingUserAccount.LastName); + responseDocument.Included[0].Relationships.Should().NotBeEmpty(); await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Subscribers).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Subscribers.ShouldHaveCount(1); + workItemInDatabase.Subscribers.Should().HaveCount(1); workItemInDatabase.Subscribers.Single().Id.Should().Be(existingUserAccount.Id); }); } @@ -321,8 +321,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ManyToMany_relationship_with_include_and_fieldsets() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - WorkTag existingTag = _fakers.WorkTag.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + WorkTag existingTag = _fakers.WorkTag.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -361,34 +361,34 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("workItems"); responseDocument.Data.SingleValue.Id.Should().Be(existingWorkItem.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldHaveCount(1); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("priority").With(value => value.Should().Be(existingWorkItem.Priority)); - responseDocument.Data.SingleValue.Relationships.ShouldHaveCount(1); + responseDocument.Data.SingleValue.Attributes.Should().HaveCount(1); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("priority").WhoseValue.Should().Be(existingWorkItem.Priority); + responseDocument.Data.SingleValue.Relationships.Should().HaveCount(1); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("tags").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("tags").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.ManyValue.ShouldHaveCount(1); + value.Should().NotBeNull(); + value.Data.ManyValue.Should().HaveCount(1); value.Data.ManyValue[0].Id.Should().Be(existingTag.StringId); }); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("workTags"); responseDocument.Included[0].Id.Should().Be(existingTag.StringId); - responseDocument.Included[0].Attributes.ShouldHaveCount(1); - responseDocument.Included[0].Attributes.ShouldContainKey("text").With(value => value.Should().Be(existingTag.Text)); + responseDocument.Included[0].Attributes.Should().HaveCount(1); + responseDocument.Included[0].Attributes.Should().ContainKey("text").WhoseValue.Should().Be(existingTag.Text); responseDocument.Included[0].Relationships.Should().BeNull(); - int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + int newWorkItemId = int.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Tags).FirstWithIdAsync(newWorkItemId); - workItemInDatabase.Tags.ShouldHaveCount(1); + workItemInDatabase.Tags.Should().HaveCount(1); workItemInDatabase.Tags.Single().Id.Should().Be(existingTag.Id); }); } @@ -397,7 +397,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_for_missing_relationship_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -435,22 +435,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/subscribers/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_replace_for_unknown_relationship_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -489,22 +489,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/subscribers/data[0]/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_replace_for_missing_relationship_ID() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -542,22 +542,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/subscribers/data[0]"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_replace_with_unknown_relationship_IDs() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -623,7 +623,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(4); + responseDocument.Errors.Should().HaveCount(4); ErrorObject error1 = responseDocument.Errors[0]; error1.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -650,7 +650,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_on_relationship_type_mismatch() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -689,25 +689,25 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Incompatible resource type found."); error.Detail.Should().Be("Type 'rgbColors' is not convertible to type 'userAccounts' of relationship 'subscribers'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/subscribers/data[0]/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_replace_with_duplicates() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(1).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(1); - UserAccount existingSubscriber = _fakers.UserAccount.Generate(); + UserAccount existingSubscriber = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -751,13 +751,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Subscribers).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Subscribers.ShouldHaveCount(1); + workItemInDatabase.Subscribers.Should().HaveCount(1); workItemInDatabase.Subscribers.Single().Id.Should().Be(existingSubscriber.Id); }); } @@ -766,7 +766,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_replace_with_missing_data_in_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -797,22 +797,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'data' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/subscribers"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_replace_with_null_data_in_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -844,22 +844,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an array, instead of 'null'."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/tags/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_replace_with_object_data_in_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -893,22 +893,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an array, instead of an object."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/tags/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_clear_cyclic_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -943,7 +943,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -957,7 +957,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_cyclic_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -992,7 +992,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1016,7 +1016,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_assign_cyclic_OneToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1055,13 +1055,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Children).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Children.ShouldHaveCount(1); + workItemInDatabase.Children.Should().HaveCount(1); workItemInDatabase.Children[0].Id.Should().Be(existingWorkItem.Id); }); } @@ -1070,7 +1070,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_assign_cyclic_ManyToMany_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1109,7 +1109,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1124,10 +1124,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // @formatter:wrap_after_property_in_chained_method_calls restore // @formatter:wrap_chained_method_calls restore - workItemInDatabase.RelatedFrom.ShouldHaveCount(1); + workItemInDatabase.RelatedFrom.Should().HaveCount(1); workItemInDatabase.RelatedFrom[0].Id.Should().Be(existingWorkItem.Id); - workItemInDatabase.RelatedTo.ShouldHaveCount(1); + workItemInDatabase.RelatedTo.Should().HaveCount(1); workItemInDatabase.RelatedTo[0].Id.Should().Be(existingWorkItem.Id); }); } @@ -1136,7 +1136,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_assign_relationship_with_blocked_capability() { // Arrange - WorkItemGroup existingWorkItemGroup = _fakers.WorkItemGroup.Generate(); + WorkItemGroup existingWorkItemGroup = _fakers.WorkItemGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1175,14 +1175,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Relationship cannot be assigned."); error.Detail.Should().Be("The relationship 'items' on resource type 'workItemGroups' cannot be assigned to."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/items"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateResourceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateResourceTests.cs index 9d328bd9e4..428c4a30d3 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateResourceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateResourceTests.cs @@ -40,7 +40,7 @@ public UpdateResourceTests(IntegrationTestContext { @@ -86,8 +86,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_unknown_attribute() { // Arrange - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); - string newFirstName = _fakers.UserAccount.Generate().FirstName; + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); + string newFirstName = _fakers.UserAccount.GenerateOne().FirstName; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -117,15 +117,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown attribute found."); error.Detail.Should().Be("Attribute 'doesNotExist' does not exist on resource type 'userAccounts'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/attributes/doesNotExist"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -135,8 +135,8 @@ public async Task Can_update_resource_with_unknown_attribute() var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.AllowUnknownFieldsInRequestBody = true; - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); - string newFirstName = _fakers.UserAccount.Generate().FirstName; + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); + string newFirstName = _fakers.UserAccount.GenerateOne().FirstName; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -181,7 +181,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_unknown_relationship() { // Arrange - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -217,15 +217,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown relationship found."); error.Detail.Should().Be("Relationship 'doesNotExist' does not exist on resource type 'userAccounts'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/doesNotExist"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] @@ -235,7 +235,7 @@ public async Task Can_update_resource_with_unknown_relationship() var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.AllowUnknownFieldsInRequestBody = true; - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -278,8 +278,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_partially_update_resource_with_guid_ID() { // Arrange - WorkItemGroup existingGroup = _fakers.WorkItemGroup.Generate(); - string newName = _fakers.WorkItemGroup.Generate().Name; + WorkItemGroup existingGroup = _fakers.WorkItemGroup.GenerateOne(); + string newName = _fakers.WorkItemGroup.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -310,12 +310,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => string groupName = $"{newName}{ImplicitlyChangingWorkItemGroupDefinition.Suffix}"; - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("workItemGroups"); responseDocument.Data.SingleValue.Id.Should().Be(existingGroup.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("name").With(value => value.Should().Be(groupName)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("isPublic").With(value => value.Should().Be(existingGroup.IsPublic)); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(groupName); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("isPublic").WhoseValue.Should().Be(existingGroup.IsPublic); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -326,16 +326,16 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }); PropertyInfo? property = typeof(WorkItemGroup).GetProperty(nameof(Identifiable.Id)); - property.ShouldNotBeNull(); - property.PropertyType.Should().Be(typeof(Guid)); + property.Should().NotBeNull(); + property.PropertyType.Should().Be(); } [Fact] public async Task Can_completely_update_resource_with_string_ID() { // Arrange - RgbColor existingColor = _fakers.RgbColor.Generate(); - string newDisplayName = _fakers.RgbColor.Generate().DisplayName; + RgbColor existingColor = _fakers.RgbColor.GenerateOne(); + string newDisplayName = _fakers.RgbColor.GenerateOne().DisplayName; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -374,16 +374,16 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }); PropertyInfo? property = typeof(RgbColor).GetProperty(nameof(Identifiable.Id)); - property.ShouldNotBeNull(); - property.PropertyType.Should().Be(typeof(string)); + property.Should().NotBeNull(); + property.PropertyType.Should().Be(); } [Fact] public async Task Can_update_resource_without_side_effects() { // Arrange - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); - UserAccount newUserAccount = _fakers.UserAccount.Generate(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); + UserAccount newUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -428,8 +428,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_side_effects() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - string newDescription = _fakers.WorkItem.Generate().Description!; + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + string newDescription = _fakers.WorkItem.GenerateOne().Description!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -461,14 +461,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => string itemDescription = $"{newDescription}{ImplicitlyChangingWorkItemDefinition.Suffix}"; - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("workItems"); responseDocument.Data.SingleValue.Id.Should().Be(existingWorkItem.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("description").With(value => value.Should().Be(itemDescription)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("dueAt").With(value => value.Should().BeNull()); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("priority").With(value => value.Should().Be(existingWorkItem.Priority)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("isImportant").With(value => value.Should().Be(existingWorkItem.IsImportant)); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("description").WhoseValue.Should().Be(itemDescription); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("dueAt").WhoseValue.Should().BeNull(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("priority").WhoseValue.Should().Be(existingWorkItem.Priority); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("isImportant").WhoseValue.Should().Be(existingWorkItem.IsImportant); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -484,8 +484,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_side_effects_with_primary_fieldset() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - string newDescription = _fakers.WorkItem.Generate().Description!; + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + string newDescription = _fakers.WorkItem.GenerateOne().Description!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -517,12 +517,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => string itemDescription = $"{newDescription}{ImplicitlyChangingWorkItemDefinition.Suffix}"; - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("workItems"); responseDocument.Data.SingleValue.Id.Should().Be(existingWorkItem.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldHaveCount(2); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("description").With(value => value.Should().Be(itemDescription)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("priority").With(value => value.Should().Be(existingWorkItem.Priority)); + responseDocument.Data.SingleValue.Attributes.Should().HaveCount(2); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("description").WhoseValue.Should().Be(itemDescription); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("priority").WhoseValue.Should().Be(existingWorkItem.Priority); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); await _testContext.RunOnDatabaseAsync(async dbContext => @@ -539,10 +539,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_side_effects_with_include_and_fieldsets() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Tags = _fakers.WorkTag.Generate(1).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Tags = _fakers.WorkTag.GenerateSet(1); - string newDescription = _fakers.WorkItem.Generate().Description!; + string newDescription = _fakers.WorkItem.GenerateOne().Description!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -574,26 +574,26 @@ await _testContext.RunOnDatabaseAsync(async dbContext => string itemDescription = $"{newDescription}{ImplicitlyChangingWorkItemDefinition.Suffix}"; - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("workItems"); responseDocument.Data.SingleValue.Id.Should().Be(existingWorkItem.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldHaveCount(2); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("description").With(value => value.Should().Be(itemDescription)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("priority").With(value => value.Should().Be(existingWorkItem.Priority)); - responseDocument.Data.SingleValue.Relationships.ShouldHaveCount(1); + responseDocument.Data.SingleValue.Attributes.Should().HaveCount(2); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("description").WhoseValue.Should().Be(itemDescription); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("priority").WhoseValue.Should().Be(existingWorkItem.Priority); + responseDocument.Data.SingleValue.Relationships.Should().HaveCount(1); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("tags").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("tags").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.ManyValue.ShouldHaveCount(1); + value.Should().NotBeNull(); + value.Data.ManyValue.Should().HaveCount(1); value.Data.ManyValue[0].Id.Should().Be(existingWorkItem.Tags.Single().StringId); }); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("workTags"); responseDocument.Included[0].Id.Should().Be(existingWorkItem.Tags.Single().StringId); - responseDocument.Included[0].Attributes.ShouldHaveCount(1); - responseDocument.Included[0].Attributes.ShouldContainKey("text").With(value => value.Should().Be(existingWorkItem.Tags.Single().Text)); + responseDocument.Included[0].Attributes.Should().HaveCount(1); + responseDocument.Included[0].Attributes.Should().ContainKey("text").WhoseValue.Should().Be(existingWorkItem.Tags.Single().Text); responseDocument.Included[0].Relationships.Should().BeNull(); await _testContext.RunOnDatabaseAsync(async dbContext => @@ -610,8 +610,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Update_resource_with_side_effects_hides_relationship_data_in_response() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Assignee = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Assignee = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -636,9 +636,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); - responseDocument.Data.SingleValue.Relationships.Values.Should().OnlyContain(value => value.ShouldNotBeNull().Data.Value == null); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); + responseDocument.Data.SingleValue.Relationships.Values.Should().OnlyContain(value => value != null && value.Data.Value == null); responseDocument.Included.Should().BeNull(); } @@ -646,7 +646,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_for_missing_request_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -664,10 +664,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - httpResponse.Content.Headers.ContentType.ShouldNotBeNull(); - httpResponse.Content.Headers.ContentType.ToString().Should().Be(HeaderConstants.MediaType); + httpResponse.Content.Headers.ContentType.Should().NotBeNull(); + httpResponse.Content.Headers.ContentType.ToString().Should().Be(JsonApiMediaType.Default.ToString()); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); @@ -681,7 +681,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_for_null_request_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -699,21 +699,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object, instead of 'null'."); error.Detail.Should().BeNull(); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_update_resource_for_missing_data() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -737,21 +737,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'data' element is required."); error.Detail.Should().BeNull(); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_update_resource_for_null_data() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -772,22 +772,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object, instead of 'null'."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_update_resource_for_array_data() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -815,22 +815,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object, instead of an array."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_update_resource_for_missing_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -854,22 +854,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_update_resource_for_unknown_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -894,22 +894,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_update_resource_for_missing_ID() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -933,22 +933,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_update_resource_on_unknown_resource_type_in_url() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -999,7 +999,7 @@ public async Task Cannot_update_resource_on_unknown_resource_ID_in_url() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -1013,7 +1013,7 @@ public async Task Cannot_update_resource_on_unknown_resource_ID_in_url() public async Task Cannot_update_on_resource_type_mismatch_between_url_and_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1038,22 +1038,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Incompatible resource type found."); error.Detail.Should().Be("Type 'rgbColors' is not convertible to type 'workItems'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_update_on_resource_ID_mismatch_between_url_and_body() { // Arrange - List existingWorkItems = _fakers.WorkItem.Generate(2); + List existingWorkItems = _fakers.WorkItem.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1078,22 +1078,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Conflicting 'id' values found."); error.Detail.Should().Be($"Expected '{existingWorkItems[1].StringId}' instead of '{existingWorkItems[0].StringId}'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/id"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_update_resource_with_readonly_attribute() { // Arrange - WorkItemGroup existingWorkItemGroup = _fakers.WorkItemGroup.Generate(); + WorkItemGroup existingWorkItemGroup = _fakers.WorkItemGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1122,22 +1122,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Attribute is read-only."); error.Detail.Should().Be("Attribute 'isDeprecated' on resource type 'workItemGroups' is read-only."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/attributes/isDeprecated"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_update_resource_for_broken_JSON_request_body() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1155,21 +1155,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body."); error.Detail.Should().StartWith("Expected end of string, but instead reached end of data."); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_change_ID_of_existing_resource() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1198,22 +1198,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Resource ID is read-only."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/attributes/id"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_update_resource_with_incompatible_ID_value() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1241,21 +1241,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body."); error.Detail.Should().Be($"Failed to convert ID '{existingWorkItem.Id}' of type 'Number' to type 'String'."); error.Source.Should().BeNull(); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_update_resource_with_incompatible_attribute_value() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1288,30 +1288,30 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Incompatible attribute value found."); error.Detail.Should().Match("Failed to convert attribute 'dueAt' with value '*start*end*' of type 'Object' to type 'Nullable'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/attributes/dueAt"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_update_resource_with_attributes_and_multiple_relationship_types() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Assignee = _fakers.UserAccount.Generate(); - existingWorkItem.Subscribers = _fakers.UserAccount.Generate(1).ToHashSet(); - existingWorkItem.Tags = _fakers.WorkTag.Generate(1).ToHashSet(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Assignee = _fakers.UserAccount.GenerateOne(); + existingWorkItem.Subscribers = _fakers.UserAccount.GenerateSet(1); + existingWorkItem.Tags = _fakers.WorkTag.GenerateSet(1); - List existingUserAccounts = _fakers.UserAccount.Generate(2); - WorkTag existingTag = _fakers.WorkTag.Generate(); + List existingUserAccounts = _fakers.UserAccount.GenerateList(2); + WorkTag existingTag = _fakers.WorkTag.GenerateOne(); - string newDescription = _fakers.WorkItem.Generate().Description!; + string newDescription = _fakers.WorkItem.GenerateOne().Description!; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1376,9 +1376,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => string itemDescription = $"{newDescription}{ImplicitlyChangingWorkItemDefinition.Suffix}"; - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("description").With(value => value.Should().Be(itemDescription)); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("description").WhoseValue.Should().Be(itemDescription); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1396,13 +1396,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => workItemInDatabase.Description.Should().Be(itemDescription); - workItemInDatabase.Assignee.ShouldNotBeNull(); + workItemInDatabase.Assignee.Should().NotBeNull(); workItemInDatabase.Assignee.Id.Should().Be(existingUserAccounts[0].Id); - workItemInDatabase.Subscribers.ShouldHaveCount(1); + workItemInDatabase.Subscribers.Should().HaveCount(1); workItemInDatabase.Subscribers.Single().Id.Should().Be(existingUserAccounts[1].Id); - workItemInDatabase.Tags.ShouldHaveCount(1); + workItemInDatabase.Tags.Should().HaveCount(1); workItemInDatabase.Tags.Single().Id.Should().Be(existingTag.Id); }); } @@ -1411,10 +1411,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_multiple_cyclic_relationship_types() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Parent = _fakers.WorkItem.Generate(); - existingWorkItem.Children = _fakers.WorkItem.Generate(1); - existingWorkItem.RelatedTo = _fakers.WorkItem.Generate(1); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Parent = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Children = _fakers.WorkItem.GenerateList(1); + existingWorkItem.RelatedTo = _fakers.WorkItem.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1472,7 +1472,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1489,16 +1489,16 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // @formatter:wrap_after_property_in_chained_method_calls restore // @formatter:wrap_chained_method_calls restore - workItemInDatabase.Parent.ShouldNotBeNull(); + workItemInDatabase.Parent.Should().NotBeNull(); workItemInDatabase.Parent.Id.Should().Be(existingWorkItem.Id); - workItemInDatabase.Children.ShouldHaveCount(1); + workItemInDatabase.Children.Should().HaveCount(1); workItemInDatabase.Children.Single().Id.Should().Be(existingWorkItem.Id); - workItemInDatabase.RelatedFrom.ShouldHaveCount(1); + workItemInDatabase.RelatedFrom.Should().HaveCount(1); workItemInDatabase.RelatedFrom.Single().Id.Should().Be(existingWorkItem.Id); - workItemInDatabase.RelatedTo.ShouldHaveCount(1); + workItemInDatabase.RelatedTo.Should().HaveCount(1); workItemInDatabase.RelatedTo.Single().Id.Should().Be(existingWorkItem.Id); }); } @@ -1507,7 +1507,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_assign_attribute_with_blocked_capability() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1536,14 +1536,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Attribute value cannot be assigned when updating resource."); error.Detail.Should().Be("The attribute 'isImportant' on resource type 'workItems' cannot be assigned to."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/attributes/isImportant"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateToOneRelationshipTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateToOneRelationshipTests.cs index e04c33d1eb..07fedff2ad 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateToOneRelationshipTests.cs @@ -29,8 +29,8 @@ public UpdateToOneRelationshipTests(IntegrationTestContext { @@ -62,7 +62,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -76,10 +76,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_OneToOne_relationship_from_principal_side() { // Arrange - WorkItemGroup existingGroup = _fakers.WorkItemGroup.Generate(); - existingGroup.Color = _fakers.RgbColor.Generate(); + WorkItemGroup existingGroup = _fakers.WorkItemGroup.GenerateOne(); + existingGroup.Color = _fakers.RgbColor.GenerateOne(); - RgbColor existingColor = _fakers.RgbColor.Generate(); + RgbColor existingColor = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -125,7 +125,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => colorInDatabase1.Group.Should().BeNull(); RgbColor colorInDatabase2 = colorsInDatabase.Single(color => color.Id == existingColor.Id); - colorInDatabase2.Group.ShouldNotBeNull(); + colorInDatabase2.Group.Should().NotBeNull(); colorInDatabase2.Group.Id.Should().Be(existingGroup.Id); }); } @@ -134,9 +134,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_OneToOne_relationship_from_dependent_side() { // Arrange - List existingGroups = _fakers.WorkItemGroup.Generate(2); - existingGroups[0].Color = _fakers.RgbColor.Generate(); - existingGroups[1].Color = _fakers.RgbColor.Generate(); + List existingGroups = _fakers.WorkItemGroup.GenerateList(2); + existingGroups[0].Color = _fakers.RgbColor.GenerateOne(); + existingGroups[1].Color = _fakers.RgbColor.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -182,17 +182,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => groupInDatabase1.Color.Should().BeNull(); WorkItemGroup groupInDatabase2 = groupsInDatabase.Single(group => group.Id == existingGroups[1].Id); - groupInDatabase2.Color.ShouldNotBeNull(); + groupInDatabase2.Color.Should().NotBeNull(); groupInDatabase2.Color.Id.Should().Be(existingGroups[0].Color!.Id); List colorsInDatabase = await dbContext.RgbColors.Include(color => color.Group).ToListAsync(); RgbColor colorInDatabase1 = colorsInDatabase.Single(color => color.Id == existingGroups[0].Color!.Id); - colorInDatabase1.Group.ShouldNotBeNull(); + colorInDatabase1.Group.Should().NotBeNull(); colorInDatabase1.Group.Id.Should().Be(existingGroups[1].Id); RgbColor? colorInDatabase2 = colorsInDatabase.SingleOrDefault(color => color.Id == existingGroups[1].Color!.Id); - colorInDatabase2.ShouldNotBeNull(); + colorInDatabase2.Should().NotBeNull(); colorInDatabase2.Group.Should().BeNull(); }); } @@ -201,8 +201,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_OneToOne_relationship() { // Arrange - RgbColor existingColor = _fakers.RgbColor.Generate(); - existingColor.Group = _fakers.WorkItemGroup.Generate(); + RgbColor existingColor = _fakers.RgbColor.GenerateOne(); + existingColor.Group = _fakers.WorkItemGroup.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -248,8 +248,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ManyToOne_relationship() { // Arrange - List existingUserAccounts = _fakers.UserAccount.Generate(2); - existingUserAccounts[0].AssignedItems = _fakers.WorkItem.Generate(2).ToHashSet(); + List existingUserAccounts = _fakers.UserAccount.GenerateList(2); + existingUserAccounts[0].AssignedItems = _fakers.WorkItem.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -285,7 +285,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -293,7 +293,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => WorkItem workItemInDatabase2 = await dbContext.WorkItems.Include(workItem => workItem.Assignee).FirstWithIdAsync(workItemId); - workItemInDatabase2.Assignee.ShouldNotBeNull(); + workItemInDatabase2.Assignee.Should().NotBeNull(); workItemInDatabase2.Assignee.Id.Should().Be(existingUserAccounts[1].Id); }); } @@ -302,8 +302,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_relationship_with_include() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -341,24 +341,24 @@ await _testContext.RunOnDatabaseAsync(async dbContext => string description = $"{existingWorkItem.Description}{ImplicitlyChangingWorkItemDefinition.Suffix}"; - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("workItems"); responseDocument.Data.SingleValue.Id.Should().Be(existingWorkItem.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("description").With(value => value.Should().Be(description)); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("description").WhoseValue.Should().Be(description); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("userAccounts"); responseDocument.Included[0].Id.Should().Be(existingUserAccount.StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("firstName").With(value => value.Should().Be(existingUserAccount.FirstName)); - responseDocument.Included[0].Attributes.ShouldContainKey("lastName").With(value => value.Should().Be(existingUserAccount.LastName)); - responseDocument.Included[0].Relationships.ShouldNotBeEmpty(); + responseDocument.Included[0].Attributes.Should().ContainKey("firstName").WhoseValue.Should().Be(existingUserAccount.FirstName); + responseDocument.Included[0].Attributes.Should().ContainKey("lastName").WhoseValue.Should().Be(existingUserAccount.LastName); + responseDocument.Included[0].Relationships.Should().NotBeEmpty(); await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Assignee).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Assignee.ShouldNotBeNull(); + workItemInDatabase.Assignee.Should().NotBeNull(); workItemInDatabase.Assignee.Id.Should().Be(existingUserAccount.Id); }); } @@ -367,10 +367,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_relationship_with_include_and_fieldsets() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - existingWorkItem.Assignee = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + existingWorkItem.Assignee = _fakers.UserAccount.GenerateOne(); - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -408,32 +408,32 @@ await _testContext.RunOnDatabaseAsync(async dbContext => string description = $"{existingWorkItem.Description}{ImplicitlyChangingWorkItemDefinition.Suffix}"; - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("workItems"); responseDocument.Data.SingleValue.Id.Should().Be(existingWorkItem.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldHaveCount(1); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("description").With(value => value.Should().Be(description)); - responseDocument.Data.SingleValue.Relationships.ShouldHaveCount(1); + responseDocument.Data.SingleValue.Attributes.Should().HaveCount(1); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("description").WhoseValue.Should().Be(description); + responseDocument.Data.SingleValue.Relationships.Should().HaveCount(1); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("assignee").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("assignee").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.SingleValue.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Data.SingleValue.Should().NotBeNull(); value.Data.SingleValue.Id.Should().Be(existingUserAccount.StringId); }); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("userAccounts"); responseDocument.Included[0].Id.Should().Be(existingUserAccount.StringId); - responseDocument.Included[0].Attributes.ShouldHaveCount(1); - responseDocument.Included[0].Attributes.ShouldContainKey("lastName").With(value => value.Should().Be(existingUserAccount.LastName)); + responseDocument.Included[0].Attributes.Should().HaveCount(1); + responseDocument.Included[0].Attributes.Should().ContainKey("lastName").WhoseValue.Should().Be(existingUserAccount.LastName); responseDocument.Included[0].Relationships.Should().BeNull(); await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Assignee).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Assignee.ShouldNotBeNull(); + workItemInDatabase.Assignee.Should().NotBeNull(); workItemInDatabase.Assignee.Id.Should().Be(existingUserAccount.Id); }); } @@ -442,8 +442,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_with_null_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -472,23 +472,23 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object, instead of 'null'."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/assignee"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_with_missing_data_in_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -519,23 +519,23 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'data' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/assignee"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_with_array_data_in_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - UserAccount existingUserAccount = _fakers.UserAccount.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); + UserAccount existingUserAccount = _fakers.UserAccount.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -574,22 +574,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Expected an object or 'null', instead of an array."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/assignee/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_for_missing_relationship_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -624,22 +624,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/assignee/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_for_unknown_relationship_type() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -675,22 +675,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Unknown resource type found."); error.Detail.Should().Be($"Resource type '{Unknown.ResourceType}' does not exist."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/assignee/data/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_for_missing_relationship_ID() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -725,22 +725,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: The 'id' element is required."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/assignee/data"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Cannot_create_with_unknown_relationship_ID() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -778,7 +778,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -792,7 +792,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_on_relationship_type_mismatch() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -828,22 +828,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Incompatible resource type found."); error.Detail.Should().Be("Type 'rgbColors' is not convertible to type 'userAccounts' of relationship 'assignee'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/assignee/data/type"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } [Fact] public async Task Can_clear_cyclic_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -878,7 +878,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -892,7 +892,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_assign_cyclic_relationship() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -928,13 +928,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); await _testContext.RunOnDatabaseAsync(async dbContext => { WorkItem workItemInDatabase = await dbContext.WorkItems.Include(workItem => workItem.Parent).FirstWithIdAsync(existingWorkItem.Id); - workItemInDatabase.Parent.ShouldNotBeNull(); + workItemInDatabase.Parent.Should().NotBeNull(); workItemInDatabase.Parent.Id.Should().Be(existingWorkItem.Id); }); } @@ -943,7 +943,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_assign_relationship_with_blocked_capability() { // Arrange - WorkItem existingWorkItem = _fakers.WorkItem.Generate(); + WorkItem existingWorkItem = _fakers.WorkItem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -979,14 +979,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Relationship cannot be assigned."); error.Detail.Should().Be("The relationship 'group' on resource type 'workItems' cannot be assigned to."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/group"); - error.Meta.ShouldContainKey("requestBody").With(value => value.ShouldNotBeNull().ToString().ShouldNotBeEmpty()); + error.Meta.Should().HaveRequestBody(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/RequiredRelationships/DefaultBehaviorDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/RequiredRelationships/DefaultBehaviorDbContext.cs index d0bea86f38..b874679563 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/RequiredRelationships/DefaultBehaviorDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/RequiredRelationships/DefaultBehaviorDbContext.cs @@ -7,7 +7,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.RequiredRelationships; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class DefaultBehaviorDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class DefaultBehaviorDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet Customers => Set(); public DbSet Orders => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/RequiredRelationships/DefaultBehaviorTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/RequiredRelationships/DefaultBehaviorTests.cs index 6184418d44..eab806308e 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/RequiredRelationships/DefaultBehaviorTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/RequiredRelationships/DefaultBehaviorTests.cs @@ -31,7 +31,7 @@ public DefaultBehaviorTests(IntegrationTestContext { @@ -143,9 +143,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Deleting_principal_side_of_required_OneToOne_relationship_triggers_cascading_delete() { // Arrange - Order existingOrder = _fakers.Order.Generate(); - existingOrder.Shipment = _fakers.Shipment.Generate(); - existingOrder.Customer = _fakers.Customer.Generate(); + Order existingOrder = _fakers.Order.GenerateOne(); + existingOrder.Shipment = _fakers.Shipment.GenerateOne(); + existingOrder.Customer = _fakers.Customer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -172,7 +172,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => shipmentInDatabase.Should().BeNull(); Customer? customerInDatabase = await dbContext.Customers.FirstWithIdOrDefaultAsync(existingOrder.Customer.Id); - customerInDatabase.ShouldNotBeNull(); + customerInDatabase.Should().NotBeNull(); }); } @@ -180,9 +180,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_clear_required_ManyToOne_relationship_at_primary_endpoint() { // Arrange - Order existingOrder = _fakers.Order.Generate(); - existingOrder.Shipment = _fakers.Shipment.Generate(); - existingOrder.Customer = _fakers.Customer.Generate(); + Order existingOrder = _fakers.Order.GenerateOne(); + existingOrder.Shipment = _fakers.Shipment.GenerateOne(); + existingOrder.Customer = _fakers.Customer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -214,13 +214,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Input validation failed."); error.Detail.Should().Be("The Customer field is required."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/customer/data"); } @@ -228,9 +228,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_clear_required_ManyToOne_relationship_at_relationship_endpoint() { // Arrange - Order existingOrder = _fakers.Order.Generate(); - existingOrder.Shipment = _fakers.Shipment.Generate(); - existingOrder.Customer = _fakers.Customer.Generate(); + Order existingOrder = _fakers.Order.GenerateOne(); + existingOrder.Shipment = _fakers.Shipment.GenerateOne(); + existingOrder.Customer = _fakers.Customer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -251,7 +251,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); @@ -263,9 +263,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Clearing_OneToMany_relationship_at_primary_endpoint_triggers_cascading_delete() { // Arrange - Order existingOrder = _fakers.Order.Generate(); - existingOrder.Shipment = _fakers.Shipment.Generate(); - existingOrder.Customer = _fakers.Customer.Generate(); + Order existingOrder = _fakers.Order.GenerateOne(); + existingOrder.Shipment = _fakers.Shipment.GenerateOne(); + existingOrder.Customer = _fakers.Customer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -313,9 +313,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Clearing_OneToMany_relationship_at_update_relationship_endpoint_triggers_cascading_delete() { // Arrange - Order existingOrder = _fakers.Order.Generate(); - existingOrder.Shipment = _fakers.Shipment.Generate(); - existingOrder.Customer = _fakers.Customer.Generate(); + Order existingOrder = _fakers.Order.GenerateOne(); + existingOrder.Shipment = _fakers.Shipment.GenerateOne(); + existingOrder.Customer = _fakers.Customer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -352,9 +352,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Clearing_OneToMany_relationship_at_delete_relationship_endpoint_triggers_cascading_delete() { // Arrange - Order existingOrder = _fakers.Order.Generate(); - existingOrder.Shipment = _fakers.Shipment.Generate(); - existingOrder.Customer = _fakers.Customer.Generate(); + Order existingOrder = _fakers.Order.GenerateOne(); + existingOrder.Shipment = _fakers.Shipment.GenerateOne(); + existingOrder.Customer = _fakers.Customer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -398,12 +398,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_reassign_dependent_side_of_ZeroOrOneToOne_relationship_at_primary_endpoint() { // Arrange - Order orderWithShipment = _fakers.Order.Generate(); - orderWithShipment.Shipment = _fakers.Shipment.Generate(); - orderWithShipment.Customer = _fakers.Customer.Generate(); + Order orderWithShipment = _fakers.Order.GenerateOne(); + orderWithShipment.Shipment = _fakers.Shipment.GenerateOne(); + orderWithShipment.Customer = _fakers.Customer.GenerateOne(); - Order orderWithoutShipment = _fakers.Order.Generate(); - orderWithoutShipment.Customer = _fakers.Customer.Generate(); + Order orderWithoutShipment = _fakers.Order.GenerateOne(); + orderWithoutShipment.Customer = _fakers.Customer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -453,12 +453,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_reassign_dependent_side_of_ZeroOrOneToOne_relationship_at_relationship_endpoint() { // Arrange - Order orderWithShipment = _fakers.Order.Generate(); - orderWithShipment.Shipment = _fakers.Shipment.Generate(); - orderWithShipment.Customer = _fakers.Customer.Generate(); + Order orderWithShipment = _fakers.Order.GenerateOne(); + orderWithShipment.Shipment = _fakers.Shipment.GenerateOne(); + orderWithShipment.Customer = _fakers.Customer.GenerateOne(); - Order orderWithoutShipment = _fakers.Order.Generate(); - orderWithoutShipment.Customer = _fakers.Customer.Generate(); + Order orderWithoutShipment = _fakers.Order.GenerateOne(); + orderWithoutShipment.Customer = _fakers.Customer.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/GiftCertificate.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/GiftCertificate.cs index 6a04e8a1ab..169df54e16 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/GiftCertificate.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/GiftCertificate.cs @@ -2,7 +2,6 @@ using JetBrains.Annotations; using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; -using TestBuildingBlocks; namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceConstructorInjection; @@ -10,14 +9,14 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceConstructorInjection; [Resource(ControllerNamespace = "JsonApiDotNetCoreTests.IntegrationTests.ResourceConstructorInjection")] public sealed class GiftCertificate(InjectionDbContext injectionDbContext) : Identifiable { - private readonly ISystemClock _systemClock = injectionDbContext.SystemClock; + private readonly TimeProvider _timeProvider = injectionDbContext.TimeProvider; [Attr] public DateTimeOffset IssueDate { get; set; } [Attr(Capabilities = AttrCapabilities.AllowView)] [NotMapped] - public bool HasExpired => IssueDate.AddYears(1) < _systemClock.UtcNow; + public bool HasExpired => IssueDate.AddYears(1) < _timeProvider.GetUtcNow(); [HasOne] public PostOffice? Issuer { get; set; } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/InjectionDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/InjectionDbContext.cs index 57ec534cae..9c89882a74 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/InjectionDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/InjectionDbContext.cs @@ -1,5 +1,4 @@ using JetBrains.Annotations; -using JsonApiDotNetCore; using Microsoft.EntityFrameworkCore; using TestBuildingBlocks; @@ -8,16 +7,16 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceConstructorInjection; [UsedImplicitly(ImplicitUseTargetFlags.Members)] public sealed class InjectionDbContext : TestableDbContext { - public ISystemClock SystemClock { get; } + public TimeProvider TimeProvider { get; } public DbSet PostOffices => Set(); public DbSet GiftCertificates => Set(); - public InjectionDbContext(DbContextOptions options, ISystemClock systemClock) + public InjectionDbContext(DbContextOptions options, TimeProvider timeProvider) : base(options) { - ArgumentGuard.NotNull(systemClock); + ArgumentNullException.ThrowIfNull(timeProvider); - SystemClock = systemClock; + TimeProvider = timeProvider; } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/InjectionFakers.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/InjectionFakers.cs index 28c7d28dd7..fc6cda269a 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/InjectionFakers.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/InjectionFakers.cs @@ -1,5 +1,4 @@ using Bogus; -using JsonApiDotNetCore; using Microsoft.Extensions.DependencyInjection; using TestBuildingBlocks; @@ -20,17 +19,20 @@ internal sealed class InjectionFakers public InjectionFakers(IServiceProvider serviceProvider) { - ArgumentGuard.NotNull(serviceProvider); + ArgumentNullException.ThrowIfNull(serviceProvider); _serviceProvider = serviceProvider; + var timeProvider = serviceProvider.GetRequiredService(); + DateTime systemTimeUtc = timeProvider.GetUtcNow().UtcDateTime; + _lazyPostOfficeFaker = new Lazy>(() => new Faker() - .MakeDeterministic() + .MakeDeterministic(systemTimeUtc) .CustomInstantiator(_ => new PostOffice(ResolveDbContext())) .RuleFor(postOffice => postOffice.Address, faker => faker.Address.FullAddress())); _lazyGiftCertificateFaker = new Lazy>(() => new Faker() - .MakeDeterministic() + .MakeDeterministic(systemTimeUtc) .CustomInstantiator(_ => new GiftCertificate(ResolveDbContext())) .RuleFor(giftCertificate => giftCertificate.IssueDate, faker => faker.Date.PastOffset().TruncateToWholeMilliseconds())); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/PostOffice.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/PostOffice.cs index 86658bb9d7..129efabe9f 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/PostOffice.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/PostOffice.cs @@ -2,7 +2,6 @@ using JetBrains.Annotations; using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; -using TestBuildingBlocks; namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceConstructorInjection; @@ -10,7 +9,7 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceConstructorInjection; [Resource(ControllerNamespace = "JsonApiDotNetCoreTests.IntegrationTests.ResourceConstructorInjection")] public sealed class PostOffice(InjectionDbContext injectionDbContext) : Identifiable { - private readonly ISystemClock _systemClock = injectionDbContext.SystemClock; + private readonly TimeProvider _timeProvider = injectionDbContext.TimeProvider; [Attr] public string Address { get; set; } = null!; @@ -24,7 +23,7 @@ public sealed class PostOffice(InjectionDbContext injectionDbContext) : Identifi private bool IsWithinOperatingHours() { - DateTimeOffset currentTime = _systemClock.UtcNow; - return currentTime.DayOfWeek is >= DayOfWeek.Monday and <= DayOfWeek.Friday && currentTime.Hour is >= 9 and <= 17; + DateTimeOffset utcNow = _timeProvider.GetUtcNow(); + return utcNow.DayOfWeek is >= DayOfWeek.Monday and <= DayOfWeek.Friday && utcNow.Hour is >= 9 and <= 17; } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/ResourceInjectionTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/ResourceInjectionTests.cs index 3f371b2a67..02fdf3fc1b 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/ResourceInjectionTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceConstructorInjection/ResourceInjectionTests.cs @@ -4,6 +4,7 @@ using JsonApiDotNetCore.Serialization.Objects; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using TestBuildingBlocks; using Xunit; @@ -11,6 +12,10 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceConstructorInjection; public sealed class ResourceInjectionTests : IClassFixture, InjectionDbContext>> { + private static readonly DateTimeOffset CurrentTime = 31.January(2021).At(17, 1).AsUtc(); + private static readonly DateTimeOffset OfficeIsOpenTime = 27.January(2021).At(13, 53).AsUtc(); + private static readonly DateTimeOffset OfficeIsClosedTime = 30.January(2021).At(21, 43).AsUtc(); + private readonly IntegrationTestContext, InjectionDbContext> _testContext; private readonly InjectionFakers _fakers; @@ -21,7 +26,10 @@ public ResourceInjectionTests(IntegrationTestContext(); testContext.UseController(); - testContext.ConfigureServices(services => services.AddSingleton()); + testContext.PostConfigureServices(services => services.Replace(ServiceDescriptor.Singleton(new FrozenTimeProvider(CurrentTime)))); + + var timeProvider = (FrozenTimeProvider)testContext.Factory.Services.GetRequiredService(); + timeProvider.Reset(); _fakers = new InjectionFakers(testContext.Factory.Services); } @@ -30,11 +38,8 @@ public ResourceInjectionTests(IntegrationTestContext(); - clock.UtcNow = 27.January(2021).AsUtc(); - - GiftCertificate certificate = _fakers.GiftCertificate.Generate(); - certificate.IssueDate = 28.January(2020).AsUtc(); + GiftCertificate certificate = _fakers.GiftCertificate.GenerateOne(); + certificate.IssueDate = CurrentTime.AddYears(-1).AddDays(1).UtcDateTime; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -50,20 +55,20 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(certificate.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("issueDate").With(value => value.Should().Be(certificate.IssueDate)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("hasExpired").With(value => value.Should().Be(false)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("issueDate").WhoseValue.Should().Be(certificate.IssueDate); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("hasExpired").WhoseValue.Should().Be(false); } [Fact] public async Task Can_filter_resources_by_ID() { // Arrange - var clock = (FrozenSystemClock)_testContext.Factory.Services.GetRequiredService(); - clock.UtcNow = 27.January(2021).At(13, 53).AsUtc(); + var timeProvider = (FrozenTimeProvider)_testContext.Factory.Services.GetRequiredService(); + timeProvider.SetUtcNow(OfficeIsOpenTime); - List postOffices = _fakers.PostOffice.Generate(2); + List postOffices = _fakers.PostOffice.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -80,21 +85,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(postOffices[1].StringId); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("address").With(value => value.Should().Be(postOffices[1].Address)); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("isOpen").With(value => value.Should().Be(true)); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("address").WhoseValue.Should().Be(postOffices[1].Address); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("isOpen").WhoseValue.Should().Be(true); } [Fact] public async Task Can_get_secondary_resource_with_fieldset() { // Arrange - var clock = (FrozenSystemClock)_testContext.Factory.Services.GetRequiredService(); - clock.UtcNow = 27.January(2021).At(13, 53).AsUtc(); + var timeProvider = (FrozenTimeProvider)_testContext.Factory.Services.GetRequiredService(); + timeProvider.SetUtcNow(OfficeIsOpenTime); - GiftCertificate certificate = _fakers.GiftCertificate.Generate(); - certificate.Issuer = _fakers.PostOffice.Generate(); + GiftCertificate certificate = _fakers.GiftCertificate.GenerateOne(); + certificate.Issuer = _fakers.PostOffice.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -110,22 +115,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(certificate.Issuer.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldHaveCount(1); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("isOpen").With(value => value.Should().Be(true)); + responseDocument.Data.SingleValue.Attributes.Should().HaveCount(1); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("isOpen").WhoseValue.Should().Be(true); } [Fact] public async Task Can_create_resource_with_ToOne_relationship_and_include() { // Arrange - var clock = (FrozenSystemClock)_testContext.Factory.Services.GetRequiredService(); - clock.UtcNow = 19.March(1998).At(6, 34).AsUtc(); + var timeProvider = (FrozenTimeProvider)_testContext.Factory.Services.GetRequiredService(); + timeProvider.SetUtcNow(OfficeIsClosedTime); - PostOffice existingOffice = _fakers.PostOffice.Generate(); + PostOffice existingOffice = _fakers.PostOffice.GenerateOne(); - DateTimeOffset newIssueDate = 18.March(1997).AsUtc(); + DateTimeOffset newIssueDate = OfficeIsClosedTime.AddYears(-1).AddDays(-1).UtcDateTime; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -164,27 +169,27 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("issueDate").With(value => value.Should().Be(newIssueDate)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("hasExpired").With(value => value.Should().Be(true)); + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("issueDate").WhoseValue.Should().Be(newIssueDate); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("hasExpired").WhoseValue.Should().Be(true); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("issuer").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("issuer").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.SingleValue.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Data.SingleValue.Should().NotBeNull(); value.Data.SingleValue.Id.Should().Be(existingOffice.StringId); }); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].With(resource => { resource.Id.Should().Be(existingOffice.StringId); - resource.Attributes.ShouldContainKey("address").With(value => value.Should().Be(existingOffice.Address)); - resource.Attributes.ShouldContainKey("isOpen").With(value => value.Should().Be(false)); + resource.Attributes.Should().ContainKey("address").WhoseValue.Should().Be(existingOffice.Address); + resource.Attributes.Should().ContainKey("isOpen").WhoseValue.Should().Be(false); }); - int newCertificateId = int.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + int newCertificateId = int.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -193,7 +198,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => certificateInDatabase.IssueDate.Should().Be(newIssueDate); - certificateInDatabase.Issuer.ShouldNotBeNull(); + certificateInDatabase.Issuer.Should().NotBeNull(); certificateInDatabase.Issuer.Id.Should().Be(existingOffice.Id); }); } @@ -202,13 +207,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_ToMany_relationship() { // Arrange - var clock = (FrozenSystemClock)_testContext.Factory.Services.GetRequiredService(); - clock.UtcNow = 19.March(1998).At(6, 34).AsUtc(); + var timeProvider = (FrozenTimeProvider)_testContext.Factory.Services.GetRequiredService(); + timeProvider.SetUtcNow(OfficeIsClosedTime); - PostOffice existingOffice = _fakers.PostOffice.Generate(); - existingOffice.GiftCertificates = _fakers.GiftCertificate.Generate(1); + PostOffice existingOffice = _fakers.PostOffice.GenerateOne(); + existingOffice.GiftCertificates = _fakers.GiftCertificate.GenerateList(1); - string newAddress = _fakers.PostOffice.Generate().Address; + string newAddress = _fakers.PostOffice.GenerateOne().Address; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -259,7 +264,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => officeInDatabase.Address.Should().Be(newAddress); - officeInDatabase.GiftCertificates.ShouldHaveCount(1); + officeInDatabase.GiftCertificates.Should().HaveCount(1); officeInDatabase.GiftCertificates[0].Id.Should().Be(existingOffice.GiftCertificates[0].Id); }); } @@ -268,7 +273,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource() { // Arrange - PostOffice existingOffice = _fakers.PostOffice.Generate(); + PostOffice existingOffice = _fakers.PostOffice.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -308,7 +313,7 @@ public async Task Cannot_delete_unknown_resource() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -320,10 +325,10 @@ public async Task Cannot_delete_unknown_resource() public async Task Can_add_to_ToMany_relationship() { // Arrange - PostOffice existingOffice = _fakers.PostOffice.Generate(); - existingOffice.GiftCertificates = _fakers.GiftCertificate.Generate(1); + PostOffice existingOffice = _fakers.PostOffice.GenerateOne(); + existingOffice.GiftCertificates = _fakers.GiftCertificate.GenerateList(1); - GiftCertificate existingCertificate = _fakers.GiftCertificate.Generate(); + GiftCertificate existingCertificate = _fakers.GiftCertificate.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -357,7 +362,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { PostOffice officeInDatabase = await dbContext.PostOffices.Include(postOffice => postOffice.GiftCertificates).FirstWithIdAsync(existingOffice.Id); - officeInDatabase.GiftCertificates.ShouldHaveCount(2); + officeInDatabase.GiftCertificates.Should().HaveCount(2); }); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/Constellation.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/Constellation.cs new file mode 100644 index 0000000000..371c72bcf8 --- /dev/null +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/Constellation.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceDefinitions.Reading; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "JsonApiDotNetCoreTests.IntegrationTests.ResourceDefinitions.Reading")] +public sealed class Constellation : Identifiable +{ + [Attr] + public string Name { get; set; } = null!; + + [Attr] + [Required] + public Season? VisibleDuring { get; set; } + + [HasMany] + public ISet Stars { get; set; } = new HashSet(); +} diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/ConstellationDefinition.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/ConstellationDefinition.cs new file mode 100644 index 0000000000..b74d3c4947 --- /dev/null +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/ConstellationDefinition.cs @@ -0,0 +1,33 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Queries.Expressions; +using JsonApiDotNetCore.Resources.Annotations; + +namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceDefinitions.Reading; + +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +public sealed class ConstellationDefinition( + IResourceGraph resourceGraph, IClientSettingsProvider clientSettingsProvider, ResourceDefinitionHitCounter hitCounter) + : HitCountingResourceDefinition(resourceGraph, hitCounter) +{ + private readonly IClientSettingsProvider _clientSettingsProvider = clientSettingsProvider; + + protected override ResourceDefinitionExtensibilityPoints ExtensibilityPointsToTrack => ResourceDefinitionExtensibilityPoints.Reading; + + public override FilterExpression? OnApplyFilter(FilterExpression? existingFilter) + { + FilterExpression? baseFilter = base.OnApplyFilter(existingFilter); + + if (_clientSettingsProvider.AreConstellationsVisibleDuringWinterHidden) + { + AttrAttribute visibleDuringAttribute = ResourceType.GetAttributeByPropertyName(nameof(Constellation.VisibleDuring)); + var visibleDuringChain = new ResourceFieldChainExpression(visibleDuringAttribute); + var visibleDuringComparison = new ComparisonExpression(ComparisonOperator.Equals, visibleDuringChain, new LiteralConstantExpression(Season.Winter)); + var notVisibleDuringComparison = new NotExpression(visibleDuringComparison); + + return LogicalExpression.Compose(LogicalOperator.And, baseFilter, notVisibleDuringComparison); + } + + return baseFilter; + } +} diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/IClientSettingsProvider.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/IClientSettingsProvider.cs index f67cd3d993..2200921901 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/IClientSettingsProvider.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/IClientSettingsProvider.cs @@ -2,6 +2,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceDefinitions.Reading; public interface IClientSettingsProvider { + bool AreVeryLargeStarsHidden { get; } + bool AreConstellationsVisibleDuringWinterHidden { get; } bool IsIncludePlanetMoonsBlocked { get; } bool ArePlanetsWithPrivateNameHidden { get; } bool IsStarGivingLightToMoonAutoIncluded { get; } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/ResourceDefinitionReadTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/ResourceDefinitionReadTests.cs index f1590b52ce..c22619a825 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/ResourceDefinitionReadTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/ResourceDefinitionReadTests.cs @@ -17,12 +17,14 @@ public ResourceDefinitionReadTests(IntegrationTestContext(); testContext.UseController(); testContext.UseController(); testContext.UseController(); testContext.ConfigureServices(services => { + services.AddResourceDefinition(); services.AddResourceDefinition(); services.AddResourceDefinition(); services.AddResourceDefinition(); @@ -50,7 +52,7 @@ public async Task Include_from_resource_definition_is_blocked() var settingsProvider = (TestClientSettingsProvider)_testContext.Factory.Services.GetRequiredService(); settingsProvider.BlockIncludePlanetMoons(); - Planet planet = _fakers.Planet.Generate(); + Planet planet = _fakers.Planet.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -67,7 +69,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); @@ -94,9 +96,9 @@ public async Task Include_from_resource_definition_is_added() var settingsProvider = (TestClientSettingsProvider)_testContext.Factory.Services.GetRequiredService(); settingsProvider.AutoIncludeStarGivingLightToMoon(); - Moon moon = _fakers.Moon.Generate(); - moon.OrbitsAround = _fakers.Planet.Generate(); - moon.IsGivenLightBy = _fakers.Star.Generate(); + Moon moon = _fakers.Moon.GenerateOne(); + moon.OrbitsAround = _fakers.Planet.GenerateOne(); + moon.IsGivenLightBy = _fakers.Star.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -112,20 +114,20 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("isGivenLightBy").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("isGivenLightBy").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Data.SingleValue.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Data.SingleValue.Should().NotBeNull(); value.Data.SingleValue.Type.Should().Be("stars"); value.Data.SingleValue.Id.Should().Be(moon.IsGivenLightBy.StringId); }); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("stars"); responseDocument.Included[0].Id.Should().Be(moon.IsGivenLightBy.StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("name").With(value => value.Should().Be(moon.IsGivenLightBy.Name)); + responseDocument.Included[0].Attributes.Should().ContainKey("name").WhoseValue.Should().Be(moon.IsGivenLightBy.Name); hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] { @@ -152,9 +154,9 @@ public async Task Include_from_included_resource_definition_is_added() var settingsProvider = (TestClientSettingsProvider)_testContext.Factory.Services.GetRequiredService(); settingsProvider.AutoIncludeStarGivingLightToMoon(); - Planet planet = _fakers.Planet.Generate(); - planet.Moons = _fakers.Moon.Generate(1).ToHashSet(); - planet.Moons.ElementAt(0).IsGivenLightBy = _fakers.Star.Generate(); + Planet planet = _fakers.Planet.GenerateOne(); + planet.Moons = _fakers.Moon.GenerateSet(1); + planet.Moons.ElementAt(0).IsGivenLightBy = _fakers.Star.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -170,17 +172,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); - responseDocument.Included.ShouldHaveCount(2); + responseDocument.Included.Should().HaveCount(2); responseDocument.Included[0].Type.Should().Be("moons"); responseDocument.Included[0].Id.Should().Be(planet.Moons.ElementAt(0).StringId); - responseDocument.Included[0].Attributes.ShouldContainKey("name").With(value => value.Should().Be(planet.Moons.ElementAt(0).Name)); + responseDocument.Included[0].Attributes.Should().ContainKey("name").WhoseValue.Should().Be(planet.Moons.ElementAt(0).Name); responseDocument.Included[1].Type.Should().Be("stars"); responseDocument.Included[1].Id.Should().Be(planet.Moons.ElementAt(0).IsGivenLightBy!.StringId); - responseDocument.Included[1].Attributes.ShouldContainKey("name").With(value => value.Should().Be(planet.Moons.ElementAt(0).IsGivenLightBy!.Name)); + responseDocument.Included[1].Attributes.Should().ContainKey("name").WhoseValue.Should().Be(planet.Moons.ElementAt(0).IsGivenLightBy!.Name); hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] { @@ -214,7 +216,7 @@ public async Task Filter_from_resource_definition_is_applied() var settingsProvider = (TestClientSettingsProvider)_testContext.Factory.Services.GetRequiredService(); settingsProvider.HidePlanetsWithPrivateName(); - List planets = _fakers.Planet.Generate(4); + List planets = _fakers.Planet.GenerateList(4); planets[0].PrivateName = "A"; planets[2].PrivateName = "B"; @@ -233,7 +235,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue[0].Id.Should().Be(planets[1].StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(planets[3].StringId); @@ -262,7 +264,7 @@ public async Task Filter_from_resource_definition_and_query_string_are_applied() var settingsProvider = (TestClientSettingsProvider)_testContext.Factory.Services.GetRequiredService(); settingsProvider.HidePlanetsWithPrivateName(); - List planets = _fakers.Planet.Generate(4); + List planets = _fakers.Planet.GenerateList(4); planets[0].HasRingSystem = true; planets[0].PrivateName = "A"; @@ -289,7 +291,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(planets[3].StringId); responseDocument.Meta.Should().ContainTotal(1); @@ -316,14 +318,13 @@ public async Task Filter_from_resource_definition_is_applied_at_secondary_endpoi var settingsProvider = (TestClientSettingsProvider)_testContext.Factory.Services.GetRequiredService(); settingsProvider.HidePlanetsWithPrivateName(); - Star star = _fakers.Star.Generate(); - star.Planets = _fakers.Planet.Generate(4).ToHashSet(); + Star star = _fakers.Star.GenerateOne(); + star.Planets = _fakers.Planet.GenerateSet(4); star.Planets.ElementAt(0).PrivateName = "A"; star.Planets.ElementAt(2).PrivateName = "B"; await _testContext.RunOnDatabaseAsync(async dbContext => { - await dbContext.ClearTableAsync(); dbContext.Stars.Add(star); await dbContext.SaveChangesAsync(); }); @@ -336,7 +337,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue[0].Id.Should().Be(star.Planets.ElementAt(1).StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(star.Planets.ElementAt(3).StringId); @@ -368,14 +369,13 @@ public async Task Filter_from_resource_definition_is_applied_at_relationship_end var settingsProvider = (TestClientSettingsProvider)_testContext.Factory.Services.GetRequiredService(); settingsProvider.HidePlanetsWithPrivateName(); - Star star = _fakers.Star.Generate(); - star.Planets = _fakers.Planet.Generate(4).ToHashSet(); + Star star = _fakers.Star.GenerateOne(); + star.Planets = _fakers.Planet.GenerateSet(4); star.Planets.ElementAt(0).PrivateName = "A"; star.Planets.ElementAt(2).PrivateName = "B"; await _testContext.RunOnDatabaseAsync(async dbContext => { - await dbContext.ClearTableAsync(); dbContext.Stars.Add(star); await dbContext.SaveChangesAsync(); }); @@ -388,7 +388,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue[0].Id.Should().Be(star.Planets.ElementAt(1).StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(star.Planets.ElementAt(3).StringId); @@ -409,13 +409,205 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }, options => options.WithStrictOrdering()); } + [Fact] + public async Task No_total_when_resource_definition_has_filter_on_inverse_ManyToOne_at_secondary_endpoint() + { + // Arrange + var hitCounter = _testContext.Factory.Services.GetRequiredService(); + + var settingsProvider = (TestClientSettingsProvider)_testContext.Factory.Services.GetRequiredService(); + settingsProvider.HideVeryLargeStars(); + + Star star = _fakers.Star.GenerateOne(); + star.Planets = _fakers.Planet.GenerateSet(1); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Stars.Add(star); + await dbContext.SaveChangesAsync(); + }); + + string route = $"/stars/{star.StringId}/planets"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecuteGetAsync(route); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); + + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Id.Should().Be(star.Planets.ElementAt(0).StringId); + + responseDocument.Meta.Should().BeNull(); + + hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] + { + (typeof(Star), ResourceDefinitionExtensibilityPoints.OnApplyFilter), + (typeof(Planet), ResourceDefinitionExtensibilityPoints.OnApplyPagination), + (typeof(Planet), ResourceDefinitionExtensibilityPoints.OnApplyFilter), + (typeof(Planet), ResourceDefinitionExtensibilityPoints.OnApplySort), + (typeof(Planet), ResourceDefinitionExtensibilityPoints.OnApplySparseFieldSet), + (typeof(Planet), ResourceDefinitionExtensibilityPoints.OnApplyIncludes), + (typeof(Star), ResourceDefinitionExtensibilityPoints.OnApplySparseFieldSet), + (typeof(Star), ResourceDefinitionExtensibilityPoints.OnApplyFilter), + (typeof(Planet), ResourceDefinitionExtensibilityPoints.OnApplySparseFieldSet), + (typeof(Planet), ResourceDefinitionExtensibilityPoints.GetMeta) + }, options => options.WithStrictOrdering()); + } + + [Fact] + public async Task Has_total_when_resource_definition_has_filter_on_inverse_ManyToMany_at_secondary_endpoint() + { + // Arrange + var hitCounter = _testContext.Factory.Services.GetRequiredService(); + + var settingsProvider = (TestClientSettingsProvider)_testContext.Factory.Services.GetRequiredService(); + settingsProvider.HideConstellationsVisibleDuringWinter(); + + Constellation constellation = _fakers.Constellation.GenerateOne(); + constellation.VisibleDuring = Season.Winter; + constellation.Stars = _fakers.Star.GenerateSet(1); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Constellations.Add(constellation); + await dbContext.SaveChangesAsync(); + }); + + string route = $"/constellations/{constellation.StringId}/stars"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecuteGetAsync(route); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); + + responseDocument.Errors.Should().HaveCount(1); + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.NotFound); + error.Title.Should().Be("The requested resource does not exist."); + error.Detail.Should().Be($"Resource of type 'constellations' with ID '{constellation.StringId}' does not exist."); + + responseDocument.Meta.Should().ContainTotal(0); + + hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] + { + (typeof(Constellation), ResourceDefinitionExtensibilityPoints.OnApplyFilter), + (typeof(Star), ResourceDefinitionExtensibilityPoints.OnApplyFilter), + (typeof(Star), ResourceDefinitionExtensibilityPoints.OnApplyPagination), + (typeof(Star), ResourceDefinitionExtensibilityPoints.OnApplyFilter), + (typeof(Star), ResourceDefinitionExtensibilityPoints.OnApplySort), + (typeof(Star), ResourceDefinitionExtensibilityPoints.OnApplySparseFieldSet), + (typeof(Star), ResourceDefinitionExtensibilityPoints.OnApplyIncludes), + (typeof(Constellation), ResourceDefinitionExtensibilityPoints.OnApplySparseFieldSet), + (typeof(Constellation), ResourceDefinitionExtensibilityPoints.OnApplyFilter) + }, options => options.WithStrictOrdering()); + } + + [Fact] + public async Task No_total_when_resource_definition_has_filter_on_inverse_ManyToOne_at_relationship_endpoint() + { + // Arrange + var hitCounter = _testContext.Factory.Services.GetRequiredService(); + + var settingsProvider = (TestClientSettingsProvider)_testContext.Factory.Services.GetRequiredService(); + settingsProvider.HideVeryLargeStars(); + + Star star = _fakers.Star.GenerateOne(); + star.Planets = _fakers.Planet.GenerateSet(1); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Stars.Add(star); + await dbContext.SaveChangesAsync(); + }); + + string route = $"/stars/{star.StringId}/relationships/planets"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecuteGetAsync(route); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); + + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Id.Should().Be(star.Planets.ElementAt(0).StringId); + + responseDocument.Meta.Should().BeNull(); + + hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] + { + (typeof(Star), ResourceDefinitionExtensibilityPoints.OnApplyFilter), + (typeof(Planet), ResourceDefinitionExtensibilityPoints.OnApplyPagination), + (typeof(Planet), ResourceDefinitionExtensibilityPoints.OnApplyFilter), + (typeof(Planet), ResourceDefinitionExtensibilityPoints.OnApplySort), + (typeof(Planet), ResourceDefinitionExtensibilityPoints.OnApplySparseFieldSet), + (typeof(Planet), ResourceDefinitionExtensibilityPoints.OnApplyIncludes), + (typeof(Planet), ResourceDefinitionExtensibilityPoints.OnApplySparseFieldSet), + (typeof(Star), ResourceDefinitionExtensibilityPoints.OnApplySparseFieldSet), + (typeof(Star), ResourceDefinitionExtensibilityPoints.OnApplyFilter) + }, options => options.WithStrictOrdering()); + } + + [Fact] + public async Task Has_total_when_resource_definition_has_filter_on_inverse_ManyToMany_at_relationship_endpoint() + { + // Arrange + var hitCounter = _testContext.Factory.Services.GetRequiredService(); + + var settingsProvider = (TestClientSettingsProvider)_testContext.Factory.Services.GetRequiredService(); + settingsProvider.HideConstellationsVisibleDuringWinter(); + + Constellation constellation = _fakers.Constellation.GenerateOne(); + constellation.VisibleDuring = Season.Winter; + constellation.Stars = _fakers.Star.GenerateSet(1); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Constellations.Add(constellation); + await dbContext.SaveChangesAsync(); + }); + + string route = $"/constellations/{constellation.StringId}/relationships/stars"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecuteGetAsync(route); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); + + responseDocument.Errors.Should().HaveCount(1); + + ErrorObject error = responseDocument.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.NotFound); + error.Title.Should().Be("The requested resource does not exist."); + error.Detail.Should().Be($"Resource of type 'constellations' with ID '{constellation.StringId}' does not exist."); + + responseDocument.Meta.Should().ContainTotal(0); + + hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] + { + (typeof(Constellation), ResourceDefinitionExtensibilityPoints.OnApplyFilter), + (typeof(Star), ResourceDefinitionExtensibilityPoints.OnApplyFilter), + (typeof(Star), ResourceDefinitionExtensibilityPoints.OnApplyPagination), + (typeof(Star), ResourceDefinitionExtensibilityPoints.OnApplyFilter), + (typeof(Star), ResourceDefinitionExtensibilityPoints.OnApplySort), + (typeof(Star), ResourceDefinitionExtensibilityPoints.OnApplySparseFieldSet), + (typeof(Star), ResourceDefinitionExtensibilityPoints.OnApplyIncludes), + (typeof(Star), ResourceDefinitionExtensibilityPoints.OnApplySparseFieldSet), + (typeof(Constellation), ResourceDefinitionExtensibilityPoints.OnApplySparseFieldSet), + (typeof(Constellation), ResourceDefinitionExtensibilityPoints.OnApplyFilter) + }, options => options.WithStrictOrdering()); + } + [Fact] public async Task Sort_from_resource_definition_is_applied() { // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - List stars = _fakers.Star.Generate(3); + List stars = _fakers.Star.GenerateList(3); stars[0].SolarMass = 500m; stars[0].SolarRadius = 1m; @@ -441,7 +633,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(3); + responseDocument.Data.ManyValue.Should().HaveCount(3); responseDocument.Data.ManyValue[0].Id.Should().Be(stars[1].StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(stars[0].StringId); responseDocument.Data.ManyValue[2].Id.Should().Be(stars[2].StringId); @@ -467,7 +659,7 @@ public async Task Sort_from_query_string_is_applied() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - List stars = _fakers.Star.Generate(3); + List stars = _fakers.Star.GenerateList(3); stars[0].Name = "B"; stars[0].SolarRadius = 10m; @@ -493,7 +685,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(3); + responseDocument.Data.ManyValue.Should().HaveCount(3); responseDocument.Data.ManyValue[0].Id.Should().Be(stars[2].StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(stars[0].StringId); responseDocument.Data.ManyValue[2].Id.Should().Be(stars[1].StringId); @@ -519,7 +711,7 @@ public async Task Page_size_from_resource_definition_is_applied() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - List stars = _fakers.Star.Generate(10); + List stars = _fakers.Star.GenerateList(10); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -536,7 +728,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(5); + responseDocument.Data.ManyValue.Should().HaveCount(5); hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] { @@ -561,7 +753,7 @@ public async Task Attribute_inclusion_from_resource_definition_is_applied_for_om // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Star star = _fakers.Star.Generate(); + Star star = _fakers.Star.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -577,11 +769,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(star.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("name").With(value => value.Should().Be(star.Name)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("kind").With(value => value.Should().Be(star.Kind)); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(star.Name); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("kind").WhoseValue.Should().Be(star.Kind); + responseDocument.Data.SingleValue.Relationships.Should().NotBeNull(); hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] { @@ -601,7 +793,7 @@ public async Task Attribute_inclusion_from_resource_definition_is_applied_for_fi // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Star star = _fakers.Star.Generate(); + Star star = _fakers.Star.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -617,11 +809,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(star.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldHaveCount(2); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("name").With(value => value.Should().Be(star.Name)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("solarRadius").With(value => value.Should().Be(star.SolarRadius)); + responseDocument.Data.SingleValue.Attributes.Should().HaveCount(2); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(star.Name); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("solarRadius").WhoseValue.Should().Be(star.SolarRadius); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] @@ -642,7 +834,7 @@ public async Task Attribute_exclusion_from_resource_definition_is_applied_for_om // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Star star = _fakers.Star.Generate(); + Star star = _fakers.Star.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -658,11 +850,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(star.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("name").With(value => value.Should().Be(star.Name)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(star.Name); responseDocument.Data.SingleValue.Attributes.Should().NotContainKey("isVisibleFromEarth"); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Relationships.Should().NotBeNull(); hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] { @@ -682,7 +874,7 @@ public async Task Attribute_exclusion_from_resource_definition_is_applied_for_fi // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Star star = _fakers.Star.Generate(); + Star star = _fakers.Star.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -698,10 +890,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(star.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldHaveCount(1); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("name").With(value => value.Should().Be(star.Name)); + responseDocument.Data.SingleValue.Attributes.Should().HaveCount(1); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("name").WhoseValue.Should().Be(star.Name); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] @@ -722,13 +914,13 @@ public async Task Queryable_parameter_handler_from_resource_definition_is_applie // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - List moons = _fakers.Moon.Generate(2); + List moons = _fakers.Moon.GenerateList(2); moons[0].SolarRadius = .5m; - moons[0].OrbitsAround = _fakers.Planet.Generate(); + moons[0].OrbitsAround = _fakers.Planet.GenerateOne(); moons[1].SolarRadius = 50m; - moons[1].OrbitsAround = _fakers.Planet.Generate(); + moons[1].OrbitsAround = _fakers.Planet.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -745,7 +937,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(moons[1].StringId); hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] @@ -769,23 +961,23 @@ public async Task Queryable_parameter_handler_from_resource_definition_and_query // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - List moons = _fakers.Moon.Generate(4); + List moons = _fakers.Moon.GenerateList(4); moons[0].Name = "Alpha1"; moons[0].SolarRadius = 1m; - moons[0].OrbitsAround = _fakers.Planet.Generate(); + moons[0].OrbitsAround = _fakers.Planet.GenerateOne(); moons[1].Name = "Alpha2"; moons[1].SolarRadius = 5m; - moons[1].OrbitsAround = _fakers.Planet.Generate(); + moons[1].OrbitsAround = _fakers.Planet.GenerateOne(); moons[2].Name = "Beta1"; moons[2].SolarRadius = 1m; - moons[2].OrbitsAround = _fakers.Planet.Generate(); + moons[2].OrbitsAround = _fakers.Planet.GenerateOne(); moons[3].Name = "Beta2"; moons[3].SolarRadius = 5m; - moons[3].OrbitsAround = _fakers.Planet.Generate(); + moons[3].OrbitsAround = _fakers.Planet.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -802,7 +994,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(moons[2].StringId); hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] @@ -826,8 +1018,8 @@ public async Task Queryable_parameter_handler_from_resource_definition_is_not_ap // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Planet planet = _fakers.Planet.Generate(); - planet.Moons = _fakers.Moon.Generate(1).ToHashSet(); + Planet planet = _fakers.Planet.GenerateOne(); + planet.Moons = _fakers.Moon.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -843,13 +1035,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Custom query string parameters cannot be used on nested resource endpoints."); error.Detail.Should().Be("Query string parameter 'isLargerThanTheSun' cannot be used on a nested resource endpoint."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("isLargerThanTheSun"); hitCounter.HitExtensibilityPoints.Should().BeEquivalentTo(new[] diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/Season.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/Season.cs new file mode 100644 index 0000000000..16e3c0d9e4 --- /dev/null +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/Season.cs @@ -0,0 +1,12 @@ +using JetBrains.Annotations; + +namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceDefinitions.Reading; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public enum Season +{ + Winter, + Spring, + Summer, + Fall +} diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/Star.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/Star.cs index e79c2ae8af..b8c78109ed 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/Star.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/Star.cs @@ -25,4 +25,7 @@ public sealed class Star : Identifiable [HasMany] public ISet Planets { get; set; } = new HashSet(); + + [HasMany] + public ISet IsPartOf { get; set; } = new HashSet(); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/StarDefinition.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/StarDefinition.cs index 944cb4ca0e..3e4f9b678c 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/StarDefinition.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/StarDefinition.cs @@ -2,16 +2,35 @@ using JetBrains.Annotations; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Queries.Expressions; +using JsonApiDotNetCore.Resources.Annotations; namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceDefinitions.Reading; [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] // The constructor parameters will be resolved from the container, which means you can take on any dependency that is also defined in the container. -public sealed class StarDefinition(IResourceGraph resourceGraph, ResourceDefinitionHitCounter hitCounter) +public sealed class StarDefinition(IResourceGraph resourceGraph, IClientSettingsProvider clientSettingsProvider, ResourceDefinitionHitCounter hitCounter) : HitCountingResourceDefinition(resourceGraph, hitCounter) { + private readonly IClientSettingsProvider _clientSettingsProvider = clientSettingsProvider; + protected override ResourceDefinitionExtensibilityPoints ExtensibilityPointsToTrack => ResourceDefinitionExtensibilityPoints.Reading; + public override FilterExpression? OnApplyFilter(FilterExpression? existingFilter) + { + FilterExpression? baseFilter = base.OnApplyFilter(existingFilter); + + if (_clientSettingsProvider.AreVeryLargeStarsHidden) + { + AttrAttribute solarRadiusAttribute = ResourceType.GetAttributeByPropertyName(nameof(Star.SolarRadius)); + var solarRadiusChain = new ResourceFieldChainExpression(solarRadiusAttribute); + var solarRadiusComparison = new ComparisonExpression(ComparisonOperator.LessThan, solarRadiusChain, new LiteralConstantExpression(2000M)); + + return LogicalExpression.Compose(LogicalOperator.And, baseFilter, solarRadiusComparison); + } + + return baseFilter; + } + public override SortExpression OnApplySort(SortExpression? existingSort) { base.OnApplySort(existingSort); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/TestClientSettingsProvider.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/TestClientSettingsProvider.cs index 0efc7a415e..65fa84a415 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/TestClientSettingsProvider.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/TestClientSettingsProvider.cs @@ -2,17 +2,31 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceDefinitions.Reading; internal sealed class TestClientSettingsProvider : IClientSettingsProvider { + public bool AreVeryLargeStarsHidden { get; private set; } + public bool AreConstellationsVisibleDuringWinterHidden { get; private set; } public bool IsIncludePlanetMoonsBlocked { get; private set; } public bool ArePlanetsWithPrivateNameHidden { get; private set; } public bool IsStarGivingLightToMoonAutoIncluded { get; private set; } public void ResetToDefaults() { + AreVeryLargeStarsHidden = false; + AreConstellationsVisibleDuringWinterHidden = false; IsIncludePlanetMoonsBlocked = false; ArePlanetsWithPrivateNameHidden = false; IsStarGivingLightToMoonAutoIncluded = false; } + public void HideVeryLargeStars() + { + AreVeryLargeStarsHidden = true; + } + + public void HideConstellationsVisibleDuringWinter() + { + AreConstellationsVisibleDuringWinterHidden = true; + } + public void BlockIncludePlanetMoons() { IsIncludePlanetMoonsBlocked = true; diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/UniverseDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/UniverseDbContext.cs index 6bfd710d0d..6a157ed8b2 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/UniverseDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/UniverseDbContext.cs @@ -5,8 +5,10 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceDefinitions.Reading; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class UniverseDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class UniverseDbContext(DbContextOptions options) + : TestableDbContext(options) { + public DbSet Constellations => Set(); public DbSet Stars => Set(); public DbSet Planets => Set(); public DbSet Moons => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/UniverseFakers.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/UniverseFakers.cs index 4c0723e1df..86ca6a70cf 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/UniverseFakers.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/UniverseFakers.cs @@ -8,6 +8,11 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceDefinitions.Reading; internal sealed class UniverseFakers { + private readonly Lazy> _lazyConstellationFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(constellation => constellation.Name, faker => faker.Random.Word()) + .RuleFor(constellation => constellation.VisibleDuring, faker => faker.PickRandom())); + private readonly Lazy> _lazyStarFaker = new(() => new Faker() .MakeDeterministic() .RuleFor(star => star.Name, faker => faker.Random.Word()) @@ -27,6 +32,7 @@ internal sealed class UniverseFakers .RuleFor(moon => moon.Name, faker => faker.Random.Word()) .RuleFor(moon => moon.SolarRadius, faker => faker.Random.Decimal(.01M, 1000M))); + public Faker Constellation => _lazyConstellationFaker.Value; public Faker Star => _lazyStarFaker.Value; public Faker Planet => _lazyPlanetFaker.Value; public Faker Moon => _lazyMoonFaker.Value; diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/AesEncryptionService.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/AesEncryptionService.cs index 07cd2c40d0..aa4417a223 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/AesEncryptionService.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/AesEncryptionService.cs @@ -9,7 +9,7 @@ public sealed class AesEncryptionService : IEncryptionService public string Encrypt(string value) { - using SymmetricAlgorithm cipher = CreateCipher(); + using Aes cipher = CreateCipher(); using ICryptoTransform transform = cipher.CreateEncryptor(); byte[] plaintext = Encoding.UTF8.GetBytes(value); @@ -26,7 +26,7 @@ public string Decrypt(string value) { byte[] buffer = Convert.FromBase64String(value); - using SymmetricAlgorithm cipher = CreateCipher(); + using Aes cipher = CreateCipher(); byte[] initVector = new byte[cipher.IV.Length]; Buffer.BlockCopy(buffer, 0, initVector, 0, initVector.Length); @@ -38,7 +38,7 @@ public string Decrypt(string value) return Encoding.UTF8.GetString(plainBytes); } - private static SymmetricAlgorithm CreateCipher() + private static Aes CreateCipher() { var cipher = Aes.Create(); cipher.Key = CryptoKey; diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/ResourceDefinitionSerializationTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/ResourceDefinitionSerializationTests.cs index 950ba84b00..02d04b03f7 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/ResourceDefinitionSerializationTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/ResourceDefinitionSerializationTests.cs @@ -42,7 +42,7 @@ public async Task Encrypts_on_get_primary_resources() var encryptionService = _testContext.Factory.Services.GetRequiredService(); var hitCounter = _testContext.Factory.Services.GetRequiredService(); - List students = _fakers.Student.Generate(2); + List students = _fakers.Student.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -59,19 +59,19 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("socialSecurityNumber").With(value => + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("socialSecurityNumber").WhoseValue.With(value => { - string stringValue = value.Should().BeOfType().Subject.ShouldNotBeNull(); + string stringValue = value.Should().BeOfType().Subject.Should().NotBeNull().And.Subject; string socialSecurityNumber = encryptionService.Decrypt(stringValue); socialSecurityNumber.Should().Be(students[0].SocialSecurityNumber); }); - responseDocument.Data.ManyValue[1].Attributes.ShouldContainKey("socialSecurityNumber").With(value => + responseDocument.Data.ManyValue[1].Attributes.Should().ContainKey("socialSecurityNumber").WhoseValue.With(value => { - string stringValue = value.Should().BeOfType().Subject.ShouldNotBeNull(); + string stringValue = value.Should().BeOfType().Subject.Should().NotBeNull().And.Subject; string socialSecurityNumber = encryptionService.Decrypt(stringValue); socialSecurityNumber.Should().Be(students[1].SocialSecurityNumber); @@ -91,9 +91,9 @@ public async Task Encrypts_on_get_primary_resources_with_ToMany_include() var encryptionService = _testContext.Factory.Services.GetRequiredService(); var hitCounter = _testContext.Factory.Services.GetRequiredService(); - List scholarships = _fakers.Scholarship.Generate(2); - scholarships[0].Participants = _fakers.Student.Generate(2); - scholarships[1].Participants = _fakers.Student.Generate(2); + List scholarships = _fakers.Scholarship.GenerateList(2); + scholarships[0].Participants = _fakers.Student.GenerateList(2); + scholarships[1].Participants = _fakers.Student.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -110,37 +110,37 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); - responseDocument.Included.ShouldHaveCount(4); + responseDocument.Included.Should().HaveCount(4); - responseDocument.Included[0].Attributes.ShouldContainKey("socialSecurityNumber").With(value => + responseDocument.Included[0].Attributes.Should().ContainKey("socialSecurityNumber").WhoseValue.With(value => { - string stringValue = value.Should().BeOfType().Subject.ShouldNotBeNull(); + string stringValue = value.Should().BeOfType().Subject.Should().NotBeNull().And.Subject; string socialSecurityNumber = encryptionService.Decrypt(stringValue); socialSecurityNumber.Should().Be(scholarships[0].Participants[0].SocialSecurityNumber); }); - responseDocument.Included[1].Attributes.ShouldContainKey("socialSecurityNumber").With(value => + responseDocument.Included[1].Attributes.Should().ContainKey("socialSecurityNumber").WhoseValue.With(value => { - string stringValue = value.Should().BeOfType().Subject.ShouldNotBeNull(); + string stringValue = value.Should().BeOfType().Subject.Should().NotBeNull().And.Subject; string socialSecurityNumber = encryptionService.Decrypt(stringValue); socialSecurityNumber.Should().Be(scholarships[0].Participants[1].SocialSecurityNumber); }); - responseDocument.Included[2].Attributes.ShouldContainKey("socialSecurityNumber").With(value => + responseDocument.Included[2].Attributes.Should().ContainKey("socialSecurityNumber").WhoseValue.With(value => { - string stringValue = value.Should().BeOfType().Subject.ShouldNotBeNull(); + string stringValue = value.Should().BeOfType().Subject.Should().NotBeNull().And.Subject; string socialSecurityNumber = encryptionService.Decrypt(stringValue); socialSecurityNumber.Should().Be(scholarships[1].Participants[0].SocialSecurityNumber); }); - responseDocument.Included[3].Attributes.ShouldContainKey("socialSecurityNumber").With(value => + responseDocument.Included[3].Attributes.Should().ContainKey("socialSecurityNumber").WhoseValue.With(value => { - string stringValue = value.Should().BeOfType().Subject.ShouldNotBeNull(); + string stringValue = value.Should().BeOfType().Subject.Should().NotBeNull().And.Subject; string socialSecurityNumber = encryptionService.Decrypt(stringValue); socialSecurityNumber.Should().Be(scholarships[1].Participants[1].SocialSecurityNumber); @@ -162,7 +162,7 @@ public async Task Encrypts_on_get_primary_resource_by_ID() var encryptionService = _testContext.Factory.Services.GetRequiredService(); var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Student student = _fakers.Student.Generate(); + Student student = _fakers.Student.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -178,11 +178,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("socialSecurityNumber").With(value => + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("socialSecurityNumber").WhoseValue.With(value => { - string stringValue = value.Should().BeOfType().Subject.ShouldNotBeNull(); + string stringValue = value.Should().BeOfType().Subject.Should().NotBeNull().And.Subject; string socialSecurityNumber = encryptionService.Decrypt(stringValue); socialSecurityNumber.Should().Be(student.SocialSecurityNumber); @@ -201,8 +201,8 @@ public async Task Encrypts_on_get_secondary_resources() var encryptionService = _testContext.Factory.Services.GetRequiredService(); var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Scholarship scholarship = _fakers.Scholarship.Generate(); - scholarship.Participants = _fakers.Student.Generate(2); + Scholarship scholarship = _fakers.Scholarship.GenerateOne(); + scholarship.Participants = _fakers.Student.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -218,19 +218,19 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("socialSecurityNumber").With(value => + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("socialSecurityNumber").WhoseValue.With(value => { - string stringValue = value.Should().BeOfType().Subject.ShouldNotBeNull(); + string stringValue = value.Should().BeOfType().Subject.Should().NotBeNull().And.Subject; string socialSecurityNumber = encryptionService.Decrypt(stringValue); socialSecurityNumber.Should().Be(scholarship.Participants[0].SocialSecurityNumber); }); - responseDocument.Data.ManyValue[1].Attributes.ShouldContainKey("socialSecurityNumber").With(value => + responseDocument.Data.ManyValue[1].Attributes.Should().ContainKey("socialSecurityNumber").WhoseValue.With(value => { - string stringValue = value.Should().BeOfType().Subject.ShouldNotBeNull(); + string stringValue = value.Should().BeOfType().Subject.Should().NotBeNull().And.Subject; string socialSecurityNumber = encryptionService.Decrypt(stringValue); socialSecurityNumber.Should().Be(scholarship.Participants[1].SocialSecurityNumber); @@ -250,8 +250,8 @@ public async Task Encrypts_on_get_secondary_resource() var encryptionService = _testContext.Factory.Services.GetRequiredService(); var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Scholarship scholarship = _fakers.Scholarship.Generate(); - scholarship.PrimaryContact = _fakers.Student.Generate(); + Scholarship scholarship = _fakers.Scholarship.GenerateOne(); + scholarship.PrimaryContact = _fakers.Student.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -267,11 +267,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("socialSecurityNumber").With(value => + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("socialSecurityNumber").WhoseValue.With(value => { - string stringValue = value.Should().BeOfType().Subject.ShouldNotBeNull(); + string stringValue = value.Should().BeOfType().Subject.Should().NotBeNull().And.Subject; string socialSecurityNumber = encryptionService.Decrypt(stringValue); socialSecurityNumber.Should().Be(scholarship.PrimaryContact.SocialSecurityNumber); @@ -290,8 +290,8 @@ public async Task Encrypts_on_get_secondary_resource_with_ToOne_include() var encryptionService = _testContext.Factory.Services.GetRequiredService(); var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Scholarship scholarship = _fakers.Scholarship.Generate(); - scholarship.PrimaryContact = _fakers.Student.Generate(); + Scholarship scholarship = _fakers.Scholarship.GenerateOne(); + scholarship.PrimaryContact = _fakers.Student.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -307,13 +307,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); - responseDocument.Included[0].Attributes.ShouldContainKey("socialSecurityNumber").With(value => + responseDocument.Included[0].Attributes.Should().ContainKey("socialSecurityNumber").WhoseValue.With(value => { - string stringValue = value.Should().BeOfType().Subject.ShouldNotBeNull(); + string stringValue = value.Should().BeOfType().Subject.Should().NotBeNull().And.Subject; string socialSecurityNumber = encryptionService.Decrypt(stringValue); socialSecurityNumber.Should().Be(scholarship.PrimaryContact.SocialSecurityNumber); @@ -332,8 +332,8 @@ public async Task Decrypts_on_create_resource() var encryptionService = _testContext.Factory.Services.GetRequiredService(); var hitCounter = _testContext.Factory.Services.GetRequiredService(); - string newName = _fakers.Student.Generate().Name; - string newSocialSecurityNumber = _fakers.Student.Generate().SocialSecurityNumber; + string newName = _fakers.Student.GenerateOne().Name; + string newSocialSecurityNumber = _fakers.Student.GenerateOne().SocialSecurityNumber; var requestBody = new { @@ -356,17 +356,17 @@ public async Task Decrypts_on_create_resource() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("socialSecurityNumber").With(value => + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("socialSecurityNumber").WhoseValue.With(value => { - string stringValue = value.Should().BeOfType().Subject.ShouldNotBeNull(); + string stringValue = value.Should().BeOfType().Subject.Should().NotBeNull().And.Subject; string socialSecurityNumber = encryptionService.Decrypt(stringValue); socialSecurityNumber.Should().Be(newSocialSecurityNumber); }); - int newStudentId = int.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + int newStudentId = int.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -389,10 +389,10 @@ public async Task Encrypts_on_create_resource_with_included_ToOne_relationship() var encryptionService = _testContext.Factory.Services.GetRequiredService(); var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Student existingStudent = _fakers.Student.Generate(); + Student existingStudent = _fakers.Student.GenerateOne(); - string newProgramName = _fakers.Scholarship.Generate().ProgramName; - decimal newAmount = _fakers.Scholarship.Generate().Amount; + string newProgramName = _fakers.Scholarship.GenerateOne().ProgramName; + decimal newAmount = _fakers.Scholarship.GenerateOne().Amount; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -432,13 +432,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); - responseDocument.Included[0].Attributes.ShouldContainKey("socialSecurityNumber").With(value => + responseDocument.Included[0].Attributes.Should().ContainKey("socialSecurityNumber").WhoseValue.With(value => { - string stringValue = value.Should().BeOfType().Subject.ShouldNotBeNull(); + string stringValue = value.Should().BeOfType().Subject.Should().NotBeNull().And.Subject; string socialSecurityNumber = encryptionService.Decrypt(stringValue); socialSecurityNumber.Should().Be(existingStudent.SocialSecurityNumber); @@ -457,9 +457,9 @@ public async Task Decrypts_on_update_resource() var encryptionService = _testContext.Factory.Services.GetRequiredService(); var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Student existingStudent = _fakers.Student.Generate(); + Student existingStudent = _fakers.Student.GenerateOne(); - string newSocialSecurityNumber = _fakers.Student.Generate().SocialSecurityNumber; + string newSocialSecurityNumber = _fakers.Student.GenerateOne().SocialSecurityNumber; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -488,11 +488,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("socialSecurityNumber").With(value => + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("socialSecurityNumber").WhoseValue.With(value => { - string stringValue = value.Should().BeOfType().Subject.ShouldNotBeNull(); + string stringValue = value.Should().BeOfType().Subject.Should().NotBeNull().And.Subject; string socialSecurityNumber = encryptionService.Decrypt(stringValue); socialSecurityNumber.Should().Be(newSocialSecurityNumber); @@ -519,10 +519,10 @@ public async Task Encrypts_on_update_resource_with_included_ToMany_relationship( var encryptionService = _testContext.Factory.Services.GetRequiredService(); var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Scholarship existingScholarship = _fakers.Scholarship.Generate(); - existingScholarship.Participants = _fakers.Student.Generate(3); + Scholarship existingScholarship = _fakers.Scholarship.GenerateOne(); + existingScholarship.Participants = _fakers.Student.GenerateList(3); - decimal newAmount = _fakers.Scholarship.Generate().Amount; + decimal newAmount = _fakers.Scholarship.GenerateOne().Amount; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -570,21 +570,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); - responseDocument.Included.ShouldHaveCount(2); + responseDocument.Included.Should().HaveCount(2); - responseDocument.Included[0].Attributes.ShouldContainKey("socialSecurityNumber").With(value => + responseDocument.Included[0].Attributes.Should().ContainKey("socialSecurityNumber").WhoseValue.With(value => { - string stringValue = value.Should().BeOfType().Subject.ShouldNotBeNull(); + string stringValue = value.Should().BeOfType().Subject.Should().NotBeNull().And.Subject; string socialSecurityNumber = encryptionService.Decrypt(stringValue); socialSecurityNumber.Should().Be(existingScholarship.Participants[0].SocialSecurityNumber); }); - responseDocument.Included[1].Attributes.ShouldContainKey("socialSecurityNumber").With(value => + responseDocument.Included[1].Attributes.Should().ContainKey("socialSecurityNumber").WhoseValue.With(value => { - string stringValue = value.Should().BeOfType().Subject.ShouldNotBeNull(); + string stringValue = value.Should().BeOfType().Subject.Should().NotBeNull().And.Subject; string socialSecurityNumber = encryptionService.Decrypt(stringValue); socialSecurityNumber.Should().Be(existingScholarship.Participants[2].SocialSecurityNumber); @@ -603,8 +603,8 @@ public async Task Skips_on_get_ToOne_relationship() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Scholarship scholarship = _fakers.Scholarship.Generate(); - scholarship.PrimaryContact = _fakers.Student.Generate(); + Scholarship scholarship = _fakers.Scholarship.GenerateOne(); + scholarship.PrimaryContact = _fakers.Student.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -620,7 +620,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be(scholarship.PrimaryContact.StringId); hitCounter.HitExtensibilityPoints.Should().BeEmpty(); @@ -632,8 +632,8 @@ public async Task Skips_on_get_ToMany_relationship() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Scholarship scholarship = _fakers.Scholarship.Generate(); - scholarship.Participants = _fakers.Student.Generate(2); + Scholarship scholarship = _fakers.Scholarship.GenerateOne(); + scholarship.Participants = _fakers.Student.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -649,7 +649,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue[0].Id.Should().Be(scholarship.Participants[0].StringId); responseDocument.Data.ManyValue[1].Id.Should().Be(scholarship.Participants[1].StringId); @@ -662,8 +662,8 @@ public async Task Skips_on_update_ToOne_relationship() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Scholarship existingScholarship = _fakers.Scholarship.Generate(); - Student existingStudent = _fakers.Student.Generate(); + Scholarship existingScholarship = _fakers.Scholarship.GenerateOne(); + Student existingStudent = _fakers.Student.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -699,8 +699,8 @@ public async Task Skips_on_set_ToMany_relationship() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Scholarship existingScholarship = _fakers.Scholarship.Generate(); - List existingStudents = _fakers.Student.Generate(2); + Scholarship existingScholarship = _fakers.Scholarship.GenerateOne(); + List existingStudents = _fakers.Student.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -745,8 +745,8 @@ public async Task Skips_on_add_to_ToMany_relationship() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Scholarship existingScholarship = _fakers.Scholarship.Generate(); - List existingStudents = _fakers.Student.Generate(2); + Scholarship existingScholarship = _fakers.Scholarship.GenerateOne(); + List existingStudents = _fakers.Student.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -791,8 +791,8 @@ public async Task Skips_on_remove_from_ToMany_relationship() // Arrange var hitCounter = _testContext.Factory.Services.GetRequiredService(); - Scholarship existingScholarship = _fakers.Scholarship.Generate(); - existingScholarship.Participants = _fakers.Student.Generate(2); + Scholarship existingScholarship = _fakers.Scholarship.GenerateOne(); + existingScholarship.Participants = _fakers.Student.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/SerializationDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/SerializationDbContext.cs index 1772f6118c..cbbf8142c5 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/SerializationDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Serialization/SerializationDbContext.cs @@ -7,7 +7,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceDefinitions.Serialization; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class SerializationDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class SerializationDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet Students => Set(); public DbSet Scholarships => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/AtomicOperationTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/AtomicOperationTests.cs new file mode 100644 index 0000000000..18253c7c7c --- /dev/null +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/AtomicOperationTests.cs @@ -0,0 +1,80 @@ +using System.Net; +using FluentAssertions; +using JsonApiDotNetCore.Serialization.Objects; +using JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance.Models; +using JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance.TablePerHierarchy; +using TestBuildingBlocks; +using Xunit; + +namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance; + +public sealed class AtomicOperationTests : IClassFixture, TablePerHierarchyDbContext>> +{ + private readonly IntegrationTestContext, TablePerHierarchyDbContext> _testContext; + private readonly ResourceInheritanceFakers _fakers = new(); + + public AtomicOperationTests(IntegrationTestContext, TablePerHierarchyDbContext> testContext) + { + _testContext = testContext; + + testContext.UseController(); + } + + [Fact] + public async Task When_operation_is_enabled_on_base_type_it_is_implicitly_enabled_on_derived_types() + { + // Arrange + AlwaysMovingTandem newMovingTandem = _fakers.AlwaysMovingTandem.GenerateOne(); + + var requestBody = new + { + atomic__operations = new[] + { + new + { + op = "add", + data = new + { + type = "alwaysMovingTandems", + attributes = new + { + weight = newMovingTandem.Weight, + requiresDriverLicense = newMovingTandem.RequiresDriverLicense, + gearCount = newMovingTandem.GearCount + } + } + } + } + }; + + const string route = "/operations"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAtomicAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); + + responseDocument.Results.Should().HaveCount(1); + + responseDocument.Results[0].Data.SingleValue.RefShould().NotBeNull().And.Subject.With(resource => + { + resource.Type.Should().Be("alwaysMovingTandems"); + resource.Attributes.Should().ContainKey("weight").WhoseValue.Should().Be(newMovingTandem.Weight); + resource.Attributes.Should().ContainKey("requiresDriverLicense").WhoseValue.Should().Be(newMovingTandem.RequiresDriverLicense); + resource.Attributes.Should().ContainKey("gearCount").WhoseValue.Should().Be(newMovingTandem.GearCount); + resource.Relationships.Should().BeNull(); + }); + + long newMovingTandemId = long.Parse(responseDocument.Results[0].Data.SingleValue!.Id.Should().NotBeNull().And.Subject); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + AlwaysMovingTandem movingTandemInDatabase = await dbContext.AlwaysMovingTandems.FirstWithIdAsync(newMovingTandemId); + + movingTandemInDatabase.Weight.Should().Be(newMovingTandem.Weight); + movingTandemInDatabase.RequiresDriverLicense.Should().Be(newMovingTandem.RequiresDriverLicense); + movingTandemInDatabase.GearCount.Should().Be(newMovingTandem.GearCount); + }); + } +} diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ChangeTracking/ChangeTrackingDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ChangeTracking/ChangeTrackingDbContext.cs index e9002e7be9..7aea8f5af1 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ChangeTracking/ChangeTrackingDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ChangeTracking/ChangeTrackingDbContext.cs @@ -1,11 +1,8 @@ using JetBrains.Annotations; -using JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance.Models; using Microsoft.EntityFrameworkCore; namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance.ChangeTracking; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class ChangeTrackingDbContext(DbContextOptions options) : ResourceInheritanceDbContext(options) -{ - public DbSet AlwaysMovingTandems => Set(); -} +public sealed class ChangeTrackingDbContext(DbContextOptions options) + : ResourceInheritanceDbContext(options); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ChangeTracking/ResourceInheritanceChangeTrackerTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ChangeTracking/ResourceInheritanceChangeTrackerTests.cs index b744a270fb..0e1201bc8f 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ChangeTracking/ResourceInheritanceChangeTrackerTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ChangeTracking/ResourceInheritanceChangeTrackerTests.cs @@ -24,9 +24,9 @@ public ResourceInheritanceChangeTrackerTests(IntegrationTestContext { @@ -55,8 +55,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("alwaysMovingTandems"); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("locationToken").With(value => value.Should().NotBe(existingMovingTandem.LocationToken)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("locationToken").WhoseValue.Should().NotBe(existingMovingTandem.LocationToken); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/Models/AlwaysMovingTandem.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/Models/AlwaysMovingTandem.cs index 5d5aa241e1..590e053339 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/Models/AlwaysMovingTandem.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/Models/AlwaysMovingTandem.cs @@ -1,11 +1,12 @@ using System.ComponentModel.DataAnnotations.Schema; using JetBrains.Annotations; +using JsonApiDotNetCore.Controllers; using JsonApiDotNetCore.Resources.Annotations; namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance.Models; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -[Resource(ControllerNamespace = "JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance")] +[Resource(ControllerNamespace = "JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance", GenerateControllerEndpoints = JsonApiEndpoints.None)] public sealed class AlwaysMovingTandem : Bike { [NotMapped] diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/Models/Tandem.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/Models/Tandem.cs index e5c3247244..d33d9c6642 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/Models/Tandem.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/Models/Tandem.cs @@ -10,6 +10,9 @@ public sealed class Tandem : Bike [Attr] public int PassengerCount { get; set; } + [HasOne] + public Box? FoldingDimensions { get; set; } + [HasMany] public ISet Features { get; set; } = new HashSet(); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/OperationsController.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/OperationsController.cs new file mode 100644 index 0000000000..6b742c8243 --- /dev/null +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/OperationsController.cs @@ -0,0 +1,13 @@ +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.Resources; +using Microsoft.Extensions.Logging; + +namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance; + +public sealed class OperationsController( + IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, IOperationsProcessor processor, IJsonApiRequest request, + ITargetedFields targetedFields, IAtomicOperationFilter operationFilter) + : JsonApiOperationsController(options, resourceGraph, loggerFactory, processor, request, targetedFields, operationFilter); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceDbContext.cs index acac25ee8a..b5db6cdf11 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceDbContext.cs @@ -6,11 +6,13 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public abstract class ResourceInheritanceDbContext(DbContextOptions options) : TestableDbContext(options) +public abstract class ResourceInheritanceDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet Vehicles => Set(); public DbSet Bikes => Set(); public DbSet Tandems => Set(); + public DbSet AlwaysMovingTandems => Set(); public DbSet MotorVehicles => Set(); public DbSet Cars => Set(); public DbSet Trucks => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceReadTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceReadTests.cs index 6f830f873f..04ee189d8a 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceReadTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceReadTests.cs @@ -20,6 +20,8 @@ protected ResourceInheritanceReadTests(IntegrationTestContext(); + testContext.UseController(); testContext.UseController(); testContext.UseController(); @@ -46,15 +48,15 @@ protected ResourceInheritanceReadTests(IntegrationTestContext { @@ -71,29 +73,29 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be(route); - responseDocument.Data.ManyValue.ShouldHaveCount(4); + responseDocument.Data.ManyValue.Should().HaveCount(4); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "bikes").Subject.With(resource => { resource.Id.Should().Be(bike.StringId); - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be($"/bikes/{bike.StringId}"); - resource.Attributes.ShouldHaveCount(3); - resource.Attributes.ShouldContainKey("weight").With(value => value.Should().Be(bike.Weight)); - resource.Attributes.ShouldContainKey("requiresDriverLicense").With(value => value.Should().Be(bike.RequiresDriverLicense)); - resource.Attributes.ShouldContainKey("gearCount").With(value => value.Should().Be(bike.GearCount)); + resource.Attributes.Should().HaveCount(3); + resource.Attributes.Should().ContainKey("weight").WhoseValue.Should().Be(bike.Weight); + resource.Attributes.Should().ContainKey("requiresDriverLicense").WhoseValue.Should().Be(bike.RequiresDriverLicense); + resource.Attributes.Should().ContainKey("gearCount").WhoseValue.Should().Be(bike.GearCount); - resource.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights"); + resource.Relationships.Should().OnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights"); - foreach ((string? name, RelationshipObject? value) in resource.Relationships) + foreach ((string name, RelationshipObject? value) in resource.Relationships) { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"/bikes/{bike.StringId}/relationships/{name}"); value.Links.Related.Should().Be($"/bikes/{bike.StringId}/{name}"); } @@ -103,21 +105,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { resource.Id.Should().Be(tandem.StringId); - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be($"/tandems/{tandem.StringId}"); - resource.Attributes.ShouldHaveCount(4); - resource.Attributes.ShouldContainKey("weight").With(value => value.Should().Be(tandem.Weight)); - resource.Attributes.ShouldContainKey("requiresDriverLicense").With(value => value.Should().Be(tandem.RequiresDriverLicense)); - resource.Attributes.ShouldContainKey("gearCount").With(value => value.Should().Be(tandem.GearCount)); - resource.Attributes.ShouldContainKey("passengerCount").With(value => value.Should().Be(tandem.PassengerCount)); + resource.Attributes.Should().HaveCount(4); + resource.Attributes.Should().ContainKey("weight").WhoseValue.Should().Be(tandem.Weight); + resource.Attributes.Should().ContainKey("requiresDriverLicense").WhoseValue.Should().Be(tandem.RequiresDriverLicense); + resource.Attributes.Should().ContainKey("gearCount").WhoseValue.Should().Be(tandem.GearCount); + resource.Attributes.Should().ContainKey("passengerCount").WhoseValue.Should().Be(tandem.PassengerCount); - resource.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "features"); + resource.Relationships.Should().OnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "foldingDimensions", "features"); - foreach ((string? name, RelationshipObject? value) in resource.Relationships) + foreach ((string name, RelationshipObject? value) in resource.Relationships) { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"/tandems/{tandem.StringId}/relationships/{name}"); value.Links.Related.Should().Be($"/tandems/{tandem.StringId}/{name}"); } @@ -127,21 +129,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { resource.Id.Should().Be(car.StringId); - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be($"/cars/{car.StringId}"); - resource.Attributes.ShouldHaveCount(4); - resource.Attributes.ShouldContainKey("weight").With(value => value.Should().Be(car.Weight)); - resource.Attributes.ShouldContainKey("requiresDriverLicense").With(value => value.Should().Be(car.RequiresDriverLicense)); - resource.Attributes.ShouldContainKey("licensePlate").With(value => value.Should().Be(car.LicensePlate)); - resource.Attributes.ShouldContainKey("seatCount").With(value => value.Should().Be(car.SeatCount)); + resource.Attributes.Should().HaveCount(4); + resource.Attributes.Should().ContainKey("weight").WhoseValue.Should().Be(car.Weight); + resource.Attributes.Should().ContainKey("requiresDriverLicense").WhoseValue.Should().Be(car.RequiresDriverLicense); + resource.Attributes.Should().ContainKey("licensePlate").WhoseValue.Should().Be(car.LicensePlate); + resource.Attributes.Should().ContainKey("seatCount").WhoseValue.Should().Be(car.SeatCount); - resource.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "engine", "navigationSystem", "features"); + resource.Relationships.Should().OnlyContainKeys("manufacturer", "wheels", "engine", "navigationSystem", "features"); - foreach ((string? name, RelationshipObject? value) in resource.Relationships) + foreach ((string name, RelationshipObject? value) in resource.Relationships) { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"/cars/{car.StringId}/relationships/{name}"); value.Links.Related.Should().Be($"/cars/{car.StringId}/{name}"); } @@ -151,21 +153,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { resource.Id.Should().Be(truck.StringId); - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be($"/trucks/{truck.StringId}"); - resource.Attributes.ShouldHaveCount(4); - resource.Attributes.ShouldContainKey("weight").With(value => value.Should().Be(truck.Weight)); - resource.Attributes.ShouldContainKey("requiresDriverLicense").With(value => value.Should().Be(truck.RequiresDriverLicense)); - resource.Attributes.ShouldContainKey("licensePlate").With(value => value.Should().Be(truck.LicensePlate)); - resource.Attributes.ShouldContainKey("loadingCapacity").With(value => value.Should().Be(truck.LoadingCapacity)); + resource.Attributes.Should().HaveCount(4); + resource.Attributes.Should().ContainKey("weight").WhoseValue.Should().Be(truck.Weight); + resource.Attributes.Should().ContainKey("requiresDriverLicense").WhoseValue.Should().Be(truck.RequiresDriverLicense); + resource.Attributes.Should().ContainKey("licensePlate").WhoseValue.Should().Be(truck.LicensePlate); + resource.Attributes.Should().ContainKey("loadingCapacity").WhoseValue.Should().Be(truck.LoadingCapacity); - resource.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "engine", "navigationSystem", "sleepingArea", "features"); + resource.Relationships.Should().OnlyContainKeys("manufacturer", "wheels", "engine", "navigationSystem", "sleepingArea", "features"); - foreach ((string? name, RelationshipObject? value) in resource.Relationships) + foreach ((string name, RelationshipObject? value) in resource.Relationships) { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"/trucks/{truck.StringId}/relationships/{name}"); value.Links.Related.Should().Be($"/trucks/{truck.StringId}/{name}"); } @@ -176,8 +178,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resources_at_concrete_base_endpoint() { // Arrange - Bike bike = _fakers.Bike.Generate(); - Tandem tandem = _fakers.Tandem.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); + Tandem tandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -194,29 +196,29 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be(route); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "bikes").Subject.With(resource => { resource.Id.Should().Be(bike.StringId); - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be($"/bikes/{bike.StringId}"); - resource.Attributes.ShouldHaveCount(3); - resource.Attributes.ShouldContainKey("weight").With(value => value.Should().Be(bike.Weight)); - resource.Attributes.ShouldContainKey("requiresDriverLicense").With(value => value.Should().Be(bike.RequiresDriverLicense)); - resource.Attributes.ShouldContainKey("gearCount").With(value => value.Should().Be(bike.GearCount)); + resource.Attributes.Should().HaveCount(3); + resource.Attributes.Should().ContainKey("weight").WhoseValue.Should().Be(bike.Weight); + resource.Attributes.Should().ContainKey("requiresDriverLicense").WhoseValue.Should().Be(bike.RequiresDriverLicense); + resource.Attributes.Should().ContainKey("gearCount").WhoseValue.Should().Be(bike.GearCount); - resource.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights"); + resource.Relationships.Should().OnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights"); - foreach ((string? name, RelationshipObject? value) in resource.Relationships) + foreach ((string name, RelationshipObject? value) in resource.Relationships) { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"/bikes/{bike.StringId}/relationships/{name}"); value.Links.Related.Should().Be($"/bikes/{bike.StringId}/{name}"); } @@ -226,21 +228,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { resource.Id.Should().Be(tandem.StringId); - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be($"/tandems/{tandem.StringId}"); - resource.Attributes.ShouldHaveCount(4); - resource.Attributes.ShouldContainKey("weight").With(value => value.Should().Be(tandem.Weight)); - resource.Attributes.ShouldContainKey("requiresDriverLicense").With(value => value.Should().Be(tandem.RequiresDriverLicense)); - resource.Attributes.ShouldContainKey("gearCount").With(value => value.Should().Be(tandem.GearCount)); - resource.Attributes.ShouldContainKey("passengerCount").With(value => value.Should().Be(tandem.PassengerCount)); + resource.Attributes.Should().HaveCount(4); + resource.Attributes.Should().ContainKey("weight").WhoseValue.Should().Be(tandem.Weight); + resource.Attributes.Should().ContainKey("requiresDriverLicense").WhoseValue.Should().Be(tandem.RequiresDriverLicense); + resource.Attributes.Should().ContainKey("gearCount").WhoseValue.Should().Be(tandem.GearCount); + resource.Attributes.Should().ContainKey("passengerCount").WhoseValue.Should().Be(tandem.PassengerCount); - resource.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "features"); + resource.Relationships.Should().OnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "foldingDimensions", "features"); - foreach ((string? name, RelationshipObject? value) in resource.Relationships) + foreach ((string name, RelationshipObject? value) in resource.Relationships) { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"/tandems/{tandem.StringId}/relationships/{name}"); value.Links.Related.Should().Be($"/tandems/{tandem.StringId}/{name}"); } @@ -251,8 +253,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resources_at_concrete_derived_endpoint() { // Arrange - Bike bike = _fakers.Bike.Generate(); - Tandem tandem = _fakers.Tandem.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); + Tandem tandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -269,30 +271,30 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be(route); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "tandems").Subject.With(resource => { resource.Id.Should().Be(tandem.StringId); - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be($"/tandems/{tandem.StringId}"); - resource.Attributes.ShouldHaveCount(4); - resource.Attributes.ShouldContainKey("weight").With(value => value.Should().Be(tandem.Weight)); - resource.Attributes.ShouldContainKey("requiresDriverLicense").With(value => value.Should().Be(tandem.RequiresDriverLicense)); - resource.Attributes.ShouldContainKey("gearCount").With(value => value.Should().Be(tandem.GearCount)); - resource.Attributes.ShouldContainKey("passengerCount").With(value => value.Should().Be(tandem.PassengerCount)); + resource.Attributes.Should().HaveCount(4); + resource.Attributes.Should().ContainKey("weight").WhoseValue.Should().Be(tandem.Weight); + resource.Attributes.Should().ContainKey("requiresDriverLicense").WhoseValue.Should().Be(tandem.RequiresDriverLicense); + resource.Attributes.Should().ContainKey("gearCount").WhoseValue.Should().Be(tandem.GearCount); + resource.Attributes.Should().ContainKey("passengerCount").WhoseValue.Should().Be(tandem.PassengerCount); - resource.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "features"); + resource.Relationships.Should().OnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "foldingDimensions", "features"); - foreach ((string? name, RelationshipObject? value) in resource.Relationships) + foreach ((string name, RelationshipObject? value) in resource.Relationships) { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"/tandems/{tandem.StringId}/relationships/{name}"); value.Links.Related.Should().Be($"/tandems/{tandem.StringId}/{name}"); } @@ -303,7 +305,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resource_at_abstract_endpoint() { // Arrange - Tandem tandem = _fakers.Tandem.Generate(); + Tandem tandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -319,18 +321,20 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("tandems"); responseDocument.Data.SingleValue.Id.Should().Be(tandem.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldOnlyContainKeys("weight", "requiresDriverLicense", "gearCount", "passengerCount"); - responseDocument.Data.SingleValue.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "features"); + responseDocument.Data.SingleValue.Attributes.Should().OnlyContainKeys("weight", "requiresDriverLicense", "gearCount", "passengerCount"); + + responseDocument.Data.SingleValue.Relationships.Should().OnlyContainKeys( + "manufacturer", "wheels", "cargoBox", "lights", "foldingDimensions", "features"); } [Fact] public async Task Can_get_primary_resource_at_concrete_base_endpoint() { // Arrange - Tandem tandem = _fakers.Tandem.Generate(); + Tandem tandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -346,18 +350,20 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("tandems"); responseDocument.Data.SingleValue.Id.Should().Be(tandem.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldOnlyContainKeys("weight", "requiresDriverLicense", "gearCount", "passengerCount"); - responseDocument.Data.SingleValue.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "features"); + responseDocument.Data.SingleValue.Attributes.Should().OnlyContainKeys("weight", "requiresDriverLicense", "gearCount", "passengerCount"); + + responseDocument.Data.SingleValue.Relationships.Should().OnlyContainKeys( + "manufacturer", "wheels", "cargoBox", "lights", "foldingDimensions", "features"); } [Fact] public async Task Can_get_primary_resource_at_concrete_derived_endpoint() { // Arrange - Tandem tandem = _fakers.Tandem.Generate(); + Tandem tandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -373,19 +379,68 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("tandems"); responseDocument.Data.SingleValue.Id.Should().Be(tandem.StringId); - responseDocument.Data.SingleValue.Attributes.ShouldOnlyContainKeys("weight", "requiresDriverLicense", "gearCount", "passengerCount"); - responseDocument.Data.SingleValue.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "features"); + responseDocument.Data.SingleValue.Attributes.Should().OnlyContainKeys("weight", "requiresDriverLicense", "gearCount", "passengerCount"); + + responseDocument.Data.SingleValue.Relationships.Should().OnlyContainKeys( + "manufacturer", "wheels", "cargoBox", "lights", "foldingDimensions", "features"); + } + + [Fact] + public async Task Can_get_primary_resource_with_derived_includes() + { + // Arrange + VehicleManufacturer manufacturer = _fakers.VehicleManufacturer.GenerateOne(); + + Bike bike = _fakers.Bike.GenerateOne(); + bike.Lights = _fakers.BicycleLight.GenerateSet(15); + manufacturer.Vehicles.Add(bike); + + Tandem tandem = _fakers.Tandem.GenerateOne(); + tandem.Features = _fakers.GenericFeature.GenerateSet(15); + manufacturer.Vehicles.Add(tandem); + + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); + car.Features = _fakers.GenericFeature.GenerateSet(15); + manufacturer.Vehicles.Add(car); + + Truck truck = _fakers.Truck.GenerateOne(); + truck.Engine = _fakers.GasolineEngine.GenerateOne(); + truck.Features = _fakers.GenericFeature.GenerateSet(15); + manufacturer.Vehicles.Add(truck); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.VehicleManufacturers.Add(manufacturer); + await dbContext.SaveChangesAsync(); + }); + + string route = $"/vehicleManufacturers/{manufacturer.StringId}?include=vehicles.lights,vehicles.features"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecuteGetAsync(route); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); + + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Type.Should().Be("vehicleManufacturers"); + responseDocument.Data.SingleValue.Id.Should().Be(manufacturer.StringId); + + responseDocument.Included.Should().NotBeNull(); + responseDocument.Included.Where(include => include.Type == "bicycleLights").Should().HaveCount(10); + responseDocument.Included.Where(include => include.Type == "genericFeatures").Should().HaveCount(10 * 3); } [Fact] public async Task Can_get_secondary_resource_at_abstract_base_endpoint() { // Arrange - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -401,28 +456,28 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be(route); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("gasolineEngines"); responseDocument.Data.SingleValue.Id.Should().Be(car.Engine.StringId); - responseDocument.Data.SingleValue.Links.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Links.Should().NotBeNull(); responseDocument.Data.SingleValue.Links.Self.Should().Be($"/gasolineEngines/{car.Engine.StringId}"); - responseDocument.Data.SingleValue.Attributes.ShouldHaveCount(4); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("isHydrocarbonBased").With(value => value.Should().Be(car.Engine.IsHydrocarbonBased)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("capacity").With(value => value.Should().Be(car.Engine.Capacity)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("serialCode").With(value => value.Should().Be(((GasolineEngine)car.Engine).SerialCode)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("volatility").With(value => value.Should().Be(((GasolineEngine)car.Engine).Volatility)); + responseDocument.Data.SingleValue.Attributes.Should().HaveCount(4); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("isHydrocarbonBased").WhoseValue.Should().Be(car.Engine.IsHydrocarbonBased); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("capacity").WhoseValue.Should().Be(car.Engine.Capacity); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("serialCode").WhoseValue.Should().Be(((GasolineEngine)car.Engine).SerialCode); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("volatility").WhoseValue.Should().Be(((GasolineEngine)car.Engine).Volatility); - responseDocument.Data.SingleValue.Relationships.ShouldHaveCount(1); + responseDocument.Data.SingleValue.Relationships.Should().HaveCount(1); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("cylinders").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("cylinders").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"/gasolineEngines/{car.Engine.StringId}/relationships/cylinders"); value.Links.Related.Should().Be($"/gasolineEngines/{car.Engine.StringId}/cylinders"); }); @@ -432,8 +487,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_secondary_resource_at_concrete_base_endpoint() { // Arrange - Tandem tandem = _fakers.Tandem.Generate(); - tandem.CargoBox = _fakers.Box.Generate(); + Tandem tandem = _fakers.Tandem.GenerateOne(); + tandem.CargoBox = _fakers.Box.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -449,19 +504,19 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be(route); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("boxes"); responseDocument.Data.SingleValue.Id.Should().Be(tandem.CargoBox.StringId); responseDocument.Data.SingleValue.Links.Should().BeNull(); - responseDocument.Data.SingleValue.Attributes.ShouldHaveCount(3); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("width").With(value => value.Should().Be(tandem.CargoBox.Width)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("height").With(value => value.Should().Be(tandem.CargoBox.Height)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("depth").With(value => value.Should().Be(tandem.CargoBox.Depth)); + responseDocument.Data.SingleValue.Attributes.Should().HaveCount(3); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("width").WhoseValue.Should().Be(tandem.CargoBox.Width); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("height").WhoseValue.Should().Be(tandem.CargoBox.Height); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("depth").WhoseValue.Should().Be(tandem.CargoBox.Depth); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); } @@ -470,8 +525,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_secondary_resource_at_concrete_derived_endpoint() { // Arrange - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -487,28 +542,28 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be(route); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("gasolineEngines"); responseDocument.Data.SingleValue.Id.Should().Be(car.Engine.StringId); - responseDocument.Data.SingleValue.Links.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Links.Should().NotBeNull(); responseDocument.Data.SingleValue.Links.Self.Should().Be($"/gasolineEngines/{car.Engine.StringId}"); - responseDocument.Data.SingleValue.Attributes.ShouldHaveCount(4); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("isHydrocarbonBased").With(value => value.Should().Be(car.Engine.IsHydrocarbonBased)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("capacity").With(value => value.Should().Be(car.Engine.Capacity)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("serialCode").With(value => value.Should().Be(((GasolineEngine)car.Engine).SerialCode)); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("volatility").With(value => value.Should().Be(((GasolineEngine)car.Engine).Volatility)); + responseDocument.Data.SingleValue.Attributes.Should().HaveCount(4); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("isHydrocarbonBased").WhoseValue.Should().Be(car.Engine.IsHydrocarbonBased); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("capacity").WhoseValue.Should().Be(car.Engine.Capacity); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("serialCode").WhoseValue.Should().Be(((GasolineEngine)car.Engine).SerialCode); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("volatility").WhoseValue.Should().Be(((GasolineEngine)car.Engine).Volatility); - responseDocument.Data.SingleValue.Relationships.ShouldHaveCount(1); + responseDocument.Data.SingleValue.Relationships.Should().HaveCount(1); - responseDocument.Data.SingleValue.Relationships.ShouldContainKey("cylinders").With(value => + responseDocument.Data.SingleValue.Relationships.Should().ContainKey("cylinders").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"/gasolineEngines/{car.Engine.StringId}/relationships/cylinders"); value.Links.Related.Should().Be($"/gasolineEngines/{car.Engine.StringId}/cylinders"); }); @@ -518,8 +573,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resource_defined_in_derived_type_at_abstract_endpoint() { // Arrange - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -535,7 +590,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -548,8 +603,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resource_defined_in_derived_type_at_concrete_base_endpoint() { // Arrange - Tandem tandem = _fakers.Tandem.Generate(); - tandem.Features = _fakers.GenericFeature.Generate(1).ToHashSet(); + Tandem tandem = _fakers.Tandem.GenerateOne(); + tandem.FoldingDimensions = _fakers.Box.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -557,7 +612,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => await dbContext.SaveChangesAsync(); }); - string route = $"/bikes/{tandem.StringId}/features"; + string route = $"/bikes/{tandem.StringId}/foldingDimensions"; // Act (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecuteGetAsync(route); @@ -565,12 +620,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); error.Title.Should().Be("The requested relationship does not exist."); - error.Detail.Should().Be("Resource of type 'bikes' does not contain a relationship named 'features'."); + error.Detail.Should().Be("Resource of type 'bikes' does not contain a relationship named 'foldingDimensions'."); error.Source.Should().BeNull(); } @@ -578,9 +633,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_secondary_resources_at_abstract_base_endpoint() { // Arrange - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); - car.Wheels = _fakers.ChromeWheel.Generate(2).Cast().Concat(_fakers.CarbonWheel.Generate(2)).ToHashSet(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); + car.Wheels = _fakers.ChromeWheel.GenerateSet(2).Concat(_fakers.CarbonWheel.GenerateSet(2)).ToHashSet(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -596,10 +651,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be(route); - responseDocument.Data.ManyValue.ShouldHaveCount(4); + responseDocument.Data.ManyValue.Should().HaveCount(4); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "chromeWheels" && resource.Id == car.Wheels.ElementAt(0).StringId); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "chromeWheels" && resource.Id == car.Wheels.ElementAt(1).StringId); @@ -608,28 +663,28 @@ await _testContext.RunOnDatabaseAsync(async dbContext => foreach (ResourceObject resource in responseDocument.Data.ManyValue.Where(value => value.Type == "chromeWheels")) { - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be($"/chromeWheels/{resource.Id}"); - resource.Attributes.ShouldOnlyContainKeys("radius", "paintColor"); + resource.Attributes.Should().OnlyContainKeys("radius", "paintColor"); } foreach (ResourceObject resource in responseDocument.Data.ManyValue.Where(value => value.Type == "carbonWheels")) { - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be($"/carbonWheels/{resource.Id}"); - resource.Attributes.ShouldOnlyContainKeys("radius", "hasTube"); + resource.Attributes.Should().OnlyContainKeys("radius", "hasTube"); } foreach (ResourceObject resource in responseDocument.Data.ManyValue) { - resource.Relationships.ShouldHaveCount(1); + resource.Relationships.Should().HaveCount(1); - resource.Relationships.ShouldContainKey("vehicle").With(value => + resource.Relationships.Should().ContainKey("vehicle").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"/{resource.Type}/{resource.Id}/relationships/vehicle"); value.Links.Related.Should().Be($"/{resource.Type}/{resource.Id}/vehicle"); }); @@ -640,8 +695,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_secondary_resources_at_concrete_base_endpoint() { // Arrange - Tandem tandem = _fakers.Tandem.Generate(); - tandem.Wheels = _fakers.ChromeWheel.Generate(2).Cast().Concat(_fakers.CarbonWheel.Generate(2)).ToHashSet(); + Tandem tandem = _fakers.Tandem.GenerateOne(); + tandem.Wheels = _fakers.ChromeWheel.GenerateSet(2).Concat(_fakers.CarbonWheel.GenerateSet(2)).ToHashSet(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -657,10 +712,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be(route); - responseDocument.Data.ManyValue.ShouldHaveCount(4); + responseDocument.Data.ManyValue.Should().HaveCount(4); responseDocument.Data.ManyValue.Should() .ContainSingle(resource => resource.Type == "chromeWheels" && resource.Id == tandem.Wheels.ElementAt(0).StringId); @@ -676,28 +731,28 @@ await _testContext.RunOnDatabaseAsync(async dbContext => foreach (ResourceObject resource in responseDocument.Data.ManyValue.Where(value => value.Type == "chromeWheels")) { - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be($"/chromeWheels/{resource.Id}"); - resource.Attributes.ShouldOnlyContainKeys("radius", "paintColor"); + resource.Attributes.Should().OnlyContainKeys("radius", "paintColor"); } foreach (ResourceObject resource in responseDocument.Data.ManyValue.Where(value => value.Type == "carbonWheels")) { - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be($"/carbonWheels/{resource.Id}"); - resource.Attributes.ShouldOnlyContainKeys("radius", "hasTube"); + resource.Attributes.Should().OnlyContainKeys("radius", "hasTube"); } foreach (ResourceObject resource in responseDocument.Data.ManyValue) { - resource.Relationships.ShouldHaveCount(1); + resource.Relationships.Should().HaveCount(1); - resource.Relationships.ShouldContainKey("vehicle").With(value => + resource.Relationships.Should().ContainKey("vehicle").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"/{resource.Type}/{resource.Id}/relationships/vehicle"); value.Links.Related.Should().Be($"/{resource.Type}/{resource.Id}/vehicle"); }); @@ -708,9 +763,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_secondary_resources_at_concrete_derived_endpoint() { // Arrange - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); - car.Wheels = _fakers.ChromeWheel.Generate(2).Cast().Concat(_fakers.CarbonWheel.Generate(2)).ToHashSet(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); + car.Wheels = _fakers.ChromeWheel.GenerateSet(2).Concat(_fakers.CarbonWheel.GenerateSet(2)).ToHashSet(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -726,10 +781,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be(route); - responseDocument.Data.ManyValue.ShouldHaveCount(4); + responseDocument.Data.ManyValue.Should().HaveCount(4); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "chromeWheels" && resource.Id == car.Wheels.ElementAt(0).StringId); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "chromeWheels" && resource.Id == car.Wheels.ElementAt(1).StringId); @@ -738,28 +793,28 @@ await _testContext.RunOnDatabaseAsync(async dbContext => foreach (ResourceObject resource in responseDocument.Data.ManyValue.Where(value => value.Type == "chromeWheels")) { - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be($"/chromeWheels/{resource.Id}"); - resource.Attributes.ShouldOnlyContainKeys("radius", "paintColor"); + resource.Attributes.Should().OnlyContainKeys("radius", "paintColor"); } foreach (ResourceObject resource in responseDocument.Data.ManyValue.Where(value => value.Type == "carbonWheels")) { - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be($"/carbonWheels/{resource.Id}"); - resource.Attributes.ShouldOnlyContainKeys("radius", "hasTube"); + resource.Attributes.Should().OnlyContainKeys("radius", "hasTube"); } foreach (ResourceObject resource in responseDocument.Data.ManyValue) { - resource.Relationships.ShouldHaveCount(1); + resource.Relationships.Should().HaveCount(1); - resource.Relationships.ShouldContainKey("vehicle").With(value => + resource.Relationships.Should().ContainKey("vehicle").WhoseValue.With(value => { - value.ShouldNotBeNull(); - value.Links.ShouldNotBeNull(); + value.Should().NotBeNull(); + value.Links.Should().NotBeNull(); value.Links.Self.Should().Be($"/{resource.Type}/{resource.Id}/relationships/vehicle"); value.Links.Related.Should().Be($"/{resource.Type}/{resource.Id}/vehicle"); }); @@ -770,9 +825,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resources_defined_in_derived_type_at_abstract_endpoint() { // Arrange - Truck truck = _fakers.Truck.Generate(); - truck.Engine = _fakers.DieselEngine.Generate(); - truck.Features = _fakers.GenericFeature.Generate(1).ToHashSet(); + Truck truck = _fakers.Truck.GenerateOne(); + truck.Engine = _fakers.DieselEngine.GenerateOne(); + truck.Features = _fakers.GenericFeature.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -788,7 +843,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -801,8 +856,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resources_defined_in_derived_type_at_concrete_base_endpoint() { // Arrange - Tandem tandem = _fakers.Tandem.Generate(); - tandem.Features = _fakers.GenericFeature.Generate(1).ToHashSet(); + Tandem tandem = _fakers.Tandem.GenerateOne(); + tandem.Features = _fakers.GenericFeature.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -818,7 +873,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -831,8 +886,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_ToOne_relationship_at_abstract_base_endpoint() { // Arrange - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -848,11 +903,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be(route); responseDocument.Links.Related.Should().Be($"/motorVehicles/{car.StringId}/engine"); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("gasolineEngines"); responseDocument.Data.SingleValue.Id.Should().Be(car.Engine.StringId); responseDocument.Data.SingleValue.Links.Should().BeNull(); @@ -862,8 +917,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_ToOne_relationship_at_concrete_base_endpoint() { // Arrange - Tandem tandem = _fakers.Tandem.Generate(); - tandem.CargoBox = _fakers.Box.Generate(); + Tandem tandem = _fakers.Tandem.GenerateOne(); + tandem.CargoBox = _fakers.Box.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -879,11 +934,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be(route); responseDocument.Links.Related.Should().Be($"/bikes/{tandem.StringId}/cargoBox"); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("boxes"); responseDocument.Data.SingleValue.Id.Should().Be(tandem.CargoBox.StringId); responseDocument.Data.SingleValue.Links.Should().BeNull(); @@ -893,8 +948,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_ToOne_relationship_at_concrete_derived_endpoint() { // Arrange - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -910,11 +965,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be(route); responseDocument.Links.Related.Should().Be($"/cars/{car.StringId}/engine"); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("gasolineEngines"); responseDocument.Data.SingleValue.Id.Should().Be(car.Engine.StringId); responseDocument.Data.SingleValue.Links.Should().BeNull(); @@ -924,8 +979,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_ToOne_relationship_defined_in_derived_type_at_abstract_endpoint() { // Arrange - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -941,7 +996,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -954,9 +1009,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_ToMany_relationship_at_abstract_base_endpoint() { // Arrange - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); - car.Wheels = _fakers.ChromeWheel.Generate(2).Cast().Concat(_fakers.CarbonWheel.Generate(2)).ToHashSet(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); + car.Wheels = _fakers.ChromeWheel.GenerateSet(2).Concat(_fakers.CarbonWheel.GenerateSet(2)).ToHashSet(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -972,11 +1027,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be(route); responseDocument.Links.Related.Should().Be($"/vehicles/{car.StringId}/wheels"); - responseDocument.Data.ManyValue.ShouldHaveCount(4); + responseDocument.Data.ManyValue.Should().HaveCount(4); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "chromeWheels" && resource.Id == car.Wheels.ElementAt(0).StringId); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "chromeWheels" && resource.Id == car.Wheels.ElementAt(1).StringId); @@ -993,8 +1048,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_ToMany_relationship_at_concrete_base_endpoint() { // Arrange - Tandem tandem = _fakers.Tandem.Generate(); - tandem.Wheels = _fakers.ChromeWheel.Generate(2).Cast().Concat(_fakers.CarbonWheel.Generate(2)).ToHashSet(); + Tandem tandem = _fakers.Tandem.GenerateOne(); + tandem.Wheels = _fakers.ChromeWheel.GenerateSet(2).Concat(_fakers.CarbonWheel.GenerateSet(2)).ToHashSet(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1010,11 +1065,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be(route); responseDocument.Links.Related.Should().Be($"/bikes/{tandem.StringId}/wheels"); - responseDocument.Data.ManyValue.ShouldHaveCount(4); + responseDocument.Data.ManyValue.Should().HaveCount(4); responseDocument.Data.ManyValue.Should() .ContainSingle(resource => resource.Type == "chromeWheels" && resource.Id == tandem.Wheels.ElementAt(0).StringId); @@ -1038,9 +1093,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_ToMany_relationship_at_concrete_derived_endpoint() { // Arrange - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); - car.Wheels = _fakers.ChromeWheel.Generate(2).Cast().Concat(_fakers.CarbonWheel.Generate(2)).ToHashSet(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); + car.Wheels = _fakers.ChromeWheel.GenerateSet(2).Concat(_fakers.CarbonWheel.GenerateSet(2)).ToHashSet(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1056,11 +1111,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Links.ShouldNotBeNull(); + responseDocument.Links.Should().NotBeNull(); responseDocument.Links.Self.Should().Be(route); responseDocument.Links.Related.Should().Be($"/cars/{car.StringId}/wheels"); - responseDocument.Data.ManyValue.ShouldHaveCount(4); + responseDocument.Data.ManyValue.Should().HaveCount(4); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "chromeWheels" && resource.Id == car.Wheels.ElementAt(0).StringId); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "chromeWheels" && resource.Id == car.Wheels.ElementAt(1).StringId); @@ -1077,9 +1132,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_ToMany_relationship_defined_in_derived_type_at_abstract_endpoint() { // Arrange - Truck truck = _fakers.Truck.Generate(); - truck.Engine = _fakers.DieselEngine.Generate(); - truck.Features = _fakers.GenericFeature.Generate(1).ToHashSet(); + Truck truck = _fakers.Truck.GenerateOne(); + truck.Engine = _fakers.DieselEngine.GenerateOne(); + truck.Features = _fakers.GenericFeature.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1095,7 +1150,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -1108,8 +1163,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_ToMany_relationship_defined_in_derived_type_at_concrete_base_endpoint() { // Arrange - Tandem tandem = _fakers.Tandem.Generate(); - tandem.Features = _fakers.GenericFeature.Generate(1).ToHashSet(); + Tandem tandem = _fakers.Tandem.GenerateOne(); + tandem.Features = _fakers.GenericFeature.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1125,7 +1180,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -1138,15 +1193,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resources_at_abstract_endpoint_with_all_sparse_fieldsets() { // Arrange - Bike bike = _fakers.Bike.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); - Tandem tandem = _fakers.Tandem.Generate(); + Tandem tandem = _fakers.Tandem.GenerateOne(); - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); - Truck truck = _fakers.Truck.Generate(); - truck.Engine = _fakers.DieselEngine.Generate(); + Truck truck = _fakers.Truck.GenerateOne(); + truck.Engine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1168,34 +1223,34 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(4); + responseDocument.Data.ManyValue.Should().HaveCount(4); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "bikes").Subject.With(resource => { resource.Id.Should().Be(bike.StringId); - resource.Attributes.ShouldOnlyContainKeys("weight", "gearCount"); - resource.Relationships.ShouldOnlyContainKeys("lights"); + resource.Attributes.Should().OnlyContainKeys("weight", "gearCount"); + resource.Relationships.Should().OnlyContainKeys("lights"); }); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "tandems").Subject.With(resource => { resource.Id.Should().Be(tandem.StringId); - resource.Attributes.ShouldOnlyContainKeys("gearCount", "passengerCount"); - resource.Relationships.ShouldOnlyContainKeys("cargoBox"); + resource.Attributes.Should().OnlyContainKeys("gearCount", "passengerCount"); + resource.Relationships.Should().OnlyContainKeys("cargoBox"); }); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "cars").Subject.With(resource => { resource.Id.Should().Be(car.StringId); - resource.Attributes.ShouldOnlyContainKeys("weight", "requiresDriverLicense", "seatCount"); - resource.Relationships.ShouldOnlyContainKeys("engine"); + resource.Attributes.Should().OnlyContainKeys("weight", "requiresDriverLicense", "seatCount"); + resource.Relationships.Should().OnlyContainKeys("engine"); }); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "trucks").Subject.With(resource => { resource.Id.Should().Be(truck.StringId); - resource.Attributes.ShouldOnlyContainKeys("loadingCapacity"); - resource.Relationships.ShouldOnlyContainKeys("sleepingArea"); + resource.Attributes.Should().OnlyContainKeys("loadingCapacity"); + resource.Relationships.Should().OnlyContainKeys("sleepingArea"); }); } @@ -1203,15 +1258,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resources_at_abstract_endpoint_with_some_sparse_fieldsets() { // Arrange - Bike bike = _fakers.Bike.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); - Tandem tandem = _fakers.Tandem.Generate(); + Tandem tandem = _fakers.Tandem.GenerateOne(); - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); - Truck truck = _fakers.Truck.Generate(); - truck.Engine = _fakers.DieselEngine.Generate(); + Truck truck = _fakers.Truck.GenerateOne(); + truck.Engine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1231,34 +1286,34 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(4); + responseDocument.Data.ManyValue.Should().HaveCount(4); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "bikes").Subject.With(resource => { resource.Id.Should().Be(bike.StringId); - resource.Attributes.ShouldOnlyContainKeys("weight", "gearCount"); - resource.Relationships.ShouldOnlyContainKeys("lights"); + resource.Attributes.Should().OnlyContainKeys("weight", "gearCount"); + resource.Relationships.Should().OnlyContainKeys("lights"); }); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "tandems").Subject.With(resource => { resource.Id.Should().Be(tandem.StringId); - resource.Attributes.ShouldOnlyContainKeys("weight", "requiresDriverLicense", "gearCount", "passengerCount"); - resource.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "lights", "cargoBox", "features"); + resource.Attributes.Should().OnlyContainKeys("weight", "requiresDriverLicense", "gearCount", "passengerCount"); + resource.Relationships.Should().OnlyContainKeys("manufacturer", "wheels", "lights", "cargoBox", "foldingDimensions", "features"); }); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "cars").Subject.With(resource => { resource.Id.Should().Be(car.StringId); - resource.Attributes.ShouldOnlyContainKeys("weight", "requiresDriverLicense", "seatCount"); - resource.Relationships.ShouldOnlyContainKeys("engine"); + resource.Attributes.Should().OnlyContainKeys("weight", "requiresDriverLicense", "seatCount"); + resource.Relationships.Should().OnlyContainKeys("engine"); }); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "trucks").Subject.With(resource => { resource.Id.Should().Be(truck.StringId); - resource.Attributes.ShouldOnlyContainKeys("weight", "requiresDriverLicense", "licensePlate", "loadingCapacity"); - resource.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "engine", "navigationSystem", "sleepingArea", "features"); + resource.Attributes.Should().OnlyContainKeys("weight", "requiresDriverLicense", "licensePlate", "loadingCapacity"); + resource.Relationships.Should().OnlyContainKeys("manufacturer", "wheels", "engine", "navigationSystem", "sleepingArea", "features"); }); } @@ -1266,8 +1321,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resources_at_concrete_base_endpoint_with_all_sparse_fieldsets() { // Arrange - Bike bike = _fakers.Bike.Generate(); - Tandem tandem = _fakers.Tandem.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); + Tandem tandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1287,22 +1342,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "bikes").Subject.With(resource => { resource.Id.Should().Be(bike.StringId); - resource.Attributes.ShouldOnlyContainKeys("weight", "gearCount"); - resource.Relationships.ShouldOnlyContainKeys("manufacturer", "lights"); + resource.Attributes.Should().OnlyContainKeys("weight", "gearCount"); + resource.Relationships.Should().OnlyContainKeys("manufacturer", "lights"); }); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "tandems").Subject.With(resource => { resource.Id.Should().Be(tandem.StringId); - resource.Attributes.ShouldOnlyContainKeys("passengerCount"); - resource.Relationships.ShouldOnlyContainKeys("cargoBox"); + resource.Attributes.Should().OnlyContainKeys("passengerCount"); + resource.Relationships.Should().OnlyContainKeys("cargoBox"); }); } @@ -1310,8 +1365,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resources_at_concrete_base_endpoint_with_some_sparse_fieldsets() { // Arrange - Bike bike = _fakers.Bike.Generate(); - Tandem tandem = _fakers.Tandem.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); + Tandem tandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1330,22 +1385,22 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "bikes").Subject.With(resource => { resource.Id.Should().Be(bike.StringId); - resource.Attributes.ShouldOnlyContainKeys("weight", "requiresDriverLicense", "gearCount"); - resource.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights"); + resource.Attributes.Should().OnlyContainKeys("weight", "requiresDriverLicense", "gearCount"); + resource.Relationships.Should().OnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights"); }); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "tandems").Subject.With(resource => { resource.Id.Should().Be(tandem.StringId); - resource.Attributes.ShouldOnlyContainKeys("passengerCount"); - resource.Relationships.ShouldOnlyContainKeys("cargoBox"); + resource.Attributes.Should().OnlyContainKeys("passengerCount"); + resource.Relationships.Should().OnlyContainKeys("cargoBox"); }); } @@ -1353,40 +1408,40 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resources_at_abstract_endpoint_with_derived_includes() { // Arrange - Bike bike = _fakers.Bike.Generate(); - bike.Manufacturer = _fakers.VehicleManufacturer.Generate(); - bike.Wheels = _fakers.CarbonWheel.Generate(1).Cast().ToHashSet(); - bike.CargoBox = _fakers.Box.Generate(); - bike.Lights = _fakers.BicycleLight.Generate(1).ToHashSet(); - - Tandem tandem = _fakers.Tandem.Generate(); - tandem.Manufacturer = _fakers.VehicleManufacturer.Generate(); - tandem.Wheels = _fakers.ChromeWheel.Generate(1).Cast().ToHashSet(); - tandem.CargoBox = _fakers.Box.Generate(); - tandem.Lights = _fakers.BicycleLight.Generate(1).ToHashSet(); - tandem.Features = _fakers.GenericFeature.Generate(1).ToHashSet(); - tandem.Features.ElementAt(0).Properties = _fakers.StringProperty.Generate(1).Cast().ToHashSet(); - ((StringProperty)tandem.Features.ElementAt(0).Properties.ElementAt(0)).Value = _fakers.StringValue.Generate(); - - Car car = _fakers.Car.Generate(); - car.Manufacturer = _fakers.VehicleManufacturer.Generate(); - car.Wheels = _fakers.CarbonWheel.Generate(1).Cast().ToHashSet(); - car.Engine = _fakers.GasolineEngine.Generate(); - ((GasolineEngine)car.Engine).Cylinders = _fakers.Cylinder.Generate(1).ToHashSet(); - car.NavigationSystem = _fakers.NavigationSystem.Generate(); - car.Features = _fakers.GenericFeature.Generate(1).ToHashSet(); - car.Features.ElementAt(0).Properties = _fakers.NumberProperty.Generate(1).Cast().ToHashSet(); - ((NumberProperty)car.Features.ElementAt(0).Properties.ElementAt(0)).Value = _fakers.NumberValue.Generate(); - - Truck truck = _fakers.Truck.Generate(); - truck.Manufacturer = _fakers.VehicleManufacturer.Generate(); - truck.Wheels = _fakers.ChromeWheel.Generate(1).Cast().ToHashSet(); - truck.Engine = _fakers.DieselEngine.Generate(); - truck.NavigationSystem = _fakers.NavigationSystem.Generate(); - truck.SleepingArea = _fakers.Box.Generate(); - truck.Features = _fakers.GenericFeature.Generate(1).ToHashSet(); - truck.Features.ElementAt(0).Properties = _fakers.StringProperty.Generate(1).Cast().ToHashSet(); - ((StringProperty)truck.Features.ElementAt(0).Properties.ElementAt(0)).Value = _fakers.StringValue.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); + bike.Manufacturer = _fakers.VehicleManufacturer.GenerateOne(); + bike.Wheels = _fakers.CarbonWheel.GenerateSet(1); + bike.CargoBox = _fakers.Box.GenerateOne(); + bike.Lights = _fakers.BicycleLight.GenerateSet(1); + + Tandem tandem = _fakers.Tandem.GenerateOne(); + tandem.Manufacturer = _fakers.VehicleManufacturer.GenerateOne(); + tandem.Wheels = _fakers.ChromeWheel.GenerateSet(1); + tandem.CargoBox = _fakers.Box.GenerateOne(); + tandem.Lights = _fakers.BicycleLight.GenerateSet(1); + tandem.Features = _fakers.GenericFeature.GenerateSet(1); + tandem.Features.ElementAt(0).Properties = _fakers.StringProperty.GenerateSet(1); + ((StringProperty)tandem.Features.ElementAt(0).Properties.ElementAt(0)).Value = _fakers.StringValue.GenerateOne(); + + Car car = _fakers.Car.GenerateOne(); + car.Manufacturer = _fakers.VehicleManufacturer.GenerateOne(); + car.Wheels = _fakers.CarbonWheel.GenerateSet(1); + car.Engine = _fakers.GasolineEngine.GenerateOne(); + ((GasolineEngine)car.Engine).Cylinders = _fakers.Cylinder.GenerateSet(1); + car.NavigationSystem = _fakers.NavigationSystem.GenerateOne(); + car.Features = _fakers.GenericFeature.GenerateSet(1); + car.Features.ElementAt(0).Properties = _fakers.NumberProperty.GenerateSet(1); + ((NumberProperty)car.Features.ElementAt(0).Properties.ElementAt(0)).Value = _fakers.NumberValue.GenerateOne(); + + Truck truck = _fakers.Truck.GenerateOne(); + truck.Manufacturer = _fakers.VehicleManufacturer.GenerateOne(); + truck.Wheels = _fakers.ChromeWheel.GenerateSet(1); + truck.Engine = _fakers.DieselEngine.GenerateOne(); + truck.NavigationSystem = _fakers.NavigationSystem.GenerateOne(); + truck.SleepingArea = _fakers.Box.GenerateOne(); + truck.Features = _fakers.GenericFeature.GenerateSet(1); + truck.Features.ElementAt(0).Properties = _fakers.StringProperty.GenerateSet(1); + ((StringProperty)truck.Features.ElementAt(0).Properties.ElementAt(0)).Value = _fakers.StringValue.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1547,6 +1602,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => "weight": {{tandem.Weight.ToString(CultureInfo.InvariantCulture)}} }, "relationships": { + "foldingDimensions": { + "links": { + "self": "/tandems/{{tandem.StringId}}/relationships/foldingDimensions", + "related": "/tandems/{{tandem.StringId}}/foldingDimensions" + } + }, "features": { "links": { "self": "/tandems/{{tandem.StringId}}/relationships/features", @@ -1710,6 +1771,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => "id": "{{bike.Manufacturer.StringId}}", "attributes": { "name": "{{bike.Manufacturer.Name}}" + }, + "relationships": { + "vehicles": { + "links": { + "self": "/vehicleManufacturers/{{bike.Manufacturer.StringId}}/relationships/vehicles", + "related": "/vehicleManufacturers/{{bike.Manufacturer.StringId}}/vehicles" + } + } + }, + "links": { + "self": "/vehicleManufacturers/{{bike.Manufacturer.StringId}}" } }, { @@ -1816,6 +1888,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => "id": "{{car.Manufacturer.StringId}}", "attributes": { "name": "{{car.Manufacturer.Name}}" + }, + "relationships": { + "vehicles": { + "links": { + "self": "/vehicleManufacturers/{{car.Manufacturer.StringId}}/relationships/vehicles", + "related": "/vehicleManufacturers/{{car.Manufacturer.StringId}}/vehicles" + } + } + }, + "links": { + "self": "/vehicleManufacturers/{{car.Manufacturer.StringId}}" } }, { @@ -1897,6 +1980,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => "id": "{{tandem.Manufacturer.StringId}}", "attributes": { "name": "{{tandem.Manufacturer.Name}}" + }, + "relationships": { + "vehicles": { + "links": { + "self": "/vehicleManufacturers/{{tandem.Manufacturer.StringId}}/relationships/vehicles", + "related": "/vehicleManufacturers/{{tandem.Manufacturer.StringId}}/vehicles" + } + } + }, + "links": { + "self": "/vehicleManufacturers/{{tandem.Manufacturer.StringId}}" } }, { @@ -1991,6 +2085,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => "id": "{{truck.Manufacturer.StringId}}", "attributes": { "name": "{{truck.Manufacturer.Name}}" + }, + "relationships": { + "vehicles": { + "links": { + "self": "/vehicleManufacturers/{{truck.Manufacturer.StringId}}/relationships/vehicles", + "related": "/vehicleManufacturers/{{truck.Manufacturer.StringId}}/vehicles" + } + } + }, + "links": { + "self": "/vehicleManufacturers/{{truck.Manufacturer.StringId}}" } }, { @@ -2021,12 +2126,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_on_derived_resource_type_at_abstract_endpoint() { // Arrange - Bike bike = _fakers.Bike.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); - Tandem tandem = _fakers.Tandem.Generate(); + Tandem tandem = _fakers.Tandem.GenerateOne(); - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2043,7 +2148,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "bikes" && resource.Id == bike.StringId); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "tandems" && resource.Id == tandem.StringId); @@ -2053,15 +2158,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_on_derived_resource_type_with_condition_at_abstract_endpoint() { // Arrange - Bike bike = _fakers.Bike.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); - Car car = _fakers.Car.Generate(); + Car car = _fakers.Car.GenerateOne(); car.LicensePlate = "XX-99-YY"; - car.Engine = _fakers.GasolineEngine.Generate(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); - Truck truck = _fakers.Truck.Generate(); + Truck truck = _fakers.Truck.GenerateOne(); truck.LicensePlate = "AA-11-BB"; - truck.Engine = _fakers.DieselEngine.Generate(); + truck.Engine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2078,7 +2183,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "trucks" && resource.Id == truck.StringId); } @@ -2087,13 +2192,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_on_derived_resource_type_and_derived_ToOne_relationship_type_at_abstract_endpoint() { // Arrange - Bike bike = _fakers.Bike.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); - Truck truck = _fakers.Truck.Generate(); - truck.Engine = _fakers.DieselEngine.Generate(); + Truck truck = _fakers.Truck.GenerateOne(); + truck.Engine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2110,7 +2215,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "trucks" && resource.Id == truck.StringId); } @@ -2119,15 +2224,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_on_derived_resource_type_and_derived_ToOne_relationship_type_with_condition_at_abstract_endpoint() { // Arrange - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); - Truck truck1 = _fakers.Truck.Generate(); - truck1.Engine = _fakers.DieselEngine.Generate(); + Truck truck1 = _fakers.Truck.GenerateOne(); + truck1.Engine = _fakers.DieselEngine.GenerateOne(); ((DieselEngine)truck1.Engine).Viscosity = 25; - Truck truck2 = _fakers.Truck.Generate(); - truck2.Engine = _fakers.DieselEngine.Generate(); + Truck truck2 = _fakers.Truck.GenerateOne(); + truck2.Engine = _fakers.DieselEngine.GenerateOne(); ((DieselEngine)truck2.Engine).Viscosity = 100; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -2145,7 +2250,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "trucks" && resource.Id == truck2.StringId); } @@ -2154,12 +2259,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_on_derived_resource_type_with_condition_at_concrete_base_endpoint() { // Arrange - Bike bike = _fakers.Bike.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); - Tandem tandem1 = _fakers.Tandem.Generate(); + Tandem tandem1 = _fakers.Tandem.GenerateOne(); - Tandem tandem2 = _fakers.Tandem.Generate(); - tandem2.Features = _fakers.GenericFeature.Generate(1).ToHashSet(); + Tandem tandem2 = _fakers.Tandem.GenerateOne(); + tandem2.Features = _fakers.GenericFeature.GenerateSet(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2176,7 +2281,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "tandems" && resource.Id == tandem2.StringId); } @@ -2185,17 +2290,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_filter_on_derived_resource_type_with_condition_at_concrete_derived_endpoint() { // Arrange - Car car1 = _fakers.Car.Generate(); - car1.Engine = _fakers.GasolineEngine.Generate(); - car1.Wheels = _fakers.CarbonWheel.Generate(4).Cast().ToHashSet(); + Car car1 = _fakers.Car.GenerateOne(); + car1.Engine = _fakers.GasolineEngine.GenerateOne(); + car1.Wheels = _fakers.CarbonWheel.GenerateSet(4); - Car car2 = _fakers.Car.Generate(); - car2.Engine = _fakers.GasolineEngine.Generate(); - car2.Wheels = _fakers.ChromeWheel.Generate(4).Cast().ToHashSet(); + Car car2 = _fakers.Car.GenerateOne(); + car2.Engine = _fakers.GasolineEngine.GenerateOne(); + car2.Wheels = _fakers.ChromeWheel.GenerateSet(4); - Car car3 = _fakers.Car.Generate(); - car3.Engine = _fakers.GasolineEngine.Generate(); - car3.Wheels = _fakers.ChromeWheel.Generate(4).Cast().ToHashSet(); + Car car3 = _fakers.Car.GenerateOne(); + car3.Engine = _fakers.GasolineEngine.GenerateOne(); + car3.Wheels = _fakers.ChromeWheel.GenerateSet(4); car3.Wheels.Cast().ElementAt(0).PaintColor = "light-gray"; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -2213,7 +2318,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue.Should().ContainSingle(resource => resource.Type == "cars" && resource.Id == car3.StringId); } @@ -2222,17 +2327,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_on_derived_attribute_at_abstract_endpoint() { // Arrange - Bike bike1 = _fakers.Bike.Generate(); + Bike bike1 = _fakers.Bike.GenerateOne(); bike1.GearCount = 3; - Bike bike2 = _fakers.Bike.Generate(); + Bike bike2 = _fakers.Bike.GenerateOne(); bike2.GearCount = 1; - Tandem tandem = _fakers.Tandem.Generate(); + Tandem tandem = _fakers.Tandem.GenerateOne(); tandem.GearCount = 2; - Car car = _fakers.Car.Generate(); - car.Engine = _fakers.GasolineEngine.Generate(); + Car car = _fakers.Car.GenerateOne(); + car.Engine = _fakers.GasolineEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2249,7 +2354,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(4); + responseDocument.Data.ManyValue.Should().HaveCount(4); responseDocument.Data.ManyValue[0].Type.Should().Be("bikes"); responseDocument.Data.ManyValue[0].Id.Should().Be(bike2.StringId); @@ -2268,12 +2373,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_on_derived_attribute_at_concrete_base_endpoint() { // Arrange - Bike bike = _fakers.Bike.Generate(); + Bike bike = _fakers.Bike.GenerateOne(); - Tandem tandem1 = _fakers.Tandem.Generate(); + Tandem tandem1 = _fakers.Tandem.GenerateOne(); tandem1.PassengerCount = 2; - Tandem tandem2 = _fakers.Tandem.Generate(); + Tandem tandem2 = _fakers.Tandem.GenerateOne(); tandem2.PassengerCount = 4; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -2291,7 +2396,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(3); + responseDocument.Data.ManyValue.Should().HaveCount(3); responseDocument.Data.ManyValue[0].Type.Should().Be("bikes"); responseDocument.Data.ManyValue[0].Id.Should().Be(bike.StringId); @@ -2307,16 +2412,16 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_on_derived_relationship_at_concrete_derived_endpoint() { // Arrange - Car car1 = _fakers.Car.Generate(); - car1.Engine = _fakers.GasolineEngine.Generate(); - ((GasolineEngine)car1.Engine).Cylinders = _fakers.Cylinder.Generate(2).ToHashSet(); + Car car1 = _fakers.Car.GenerateOne(); + car1.Engine = _fakers.GasolineEngine.GenerateOne(); + ((GasolineEngine)car1.Engine).Cylinders = _fakers.Cylinder.GenerateSet(2); - Car car2 = _fakers.Car.Generate(); - car2.Engine = _fakers.DieselEngine.Generate(); + Car car2 = _fakers.Car.GenerateOne(); + car2.Engine = _fakers.DieselEngine.GenerateOne(); - Car car3 = _fakers.Car.Generate(); - car3.Engine = _fakers.GasolineEngine.Generate(); - ((GasolineEngine)car3.Engine).Cylinders = _fakers.Cylinder.Generate(4).ToHashSet(); + Car car3 = _fakers.Car.GenerateOne(); + car3.Engine = _fakers.GasolineEngine.GenerateOne(); + ((GasolineEngine)car3.Engine).Cylinders = _fakers.Cylinder.GenerateSet(4); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2333,7 +2438,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(3); + responseDocument.Data.ManyValue.Should().HaveCount(3); responseDocument.Data.ManyValue[0].Type.Should().Be("cars"); responseDocument.Data.ManyValue[0].Id.Should().Be(car3.StringId); @@ -2358,13 +2463,13 @@ public async Task Cannot_sort_on_ambiguous_derived_attribute() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified sort is invalid."); error.Detail.Should().Be($"Field 'serialCode' is defined on multiple types that derive from resource type 'engines'. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("sort"); } @@ -2381,13 +2486,13 @@ public async Task Cannot_sort_on_ambiguous_derived_relationship() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified sort is invalid."); error.Detail.Should().Be($"Field 'features' is defined on multiple types that derive from resource type 'vehicles'. {parameterValue}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("sort"); } @@ -2395,25 +2500,25 @@ public async Task Cannot_sort_on_ambiguous_derived_relationship() public async Task Can_sort_on_derived_attribute_from_resource_definition_using_expression_syntax() { // Arrange - ChromeWheel chromeWheel1 = _fakers.ChromeWheel.Generate(); + ChromeWheel chromeWheel1 = _fakers.ChromeWheel.GenerateOne(); chromeWheel1.PaintColor = "blue"; - chromeWheel1.Vehicle = _fakers.Car.Generate(); - ((Car)chromeWheel1.Vehicle).Engine = _fakers.GasolineEngine.Generate(); - ((GasolineEngine)((Car)chromeWheel1.Vehicle).Engine).Cylinders = _fakers.Cylinder.Generate(2).ToHashSet(); + chromeWheel1.Vehicle = _fakers.Car.GenerateOne(); + ((Car)chromeWheel1.Vehicle).Engine = _fakers.GasolineEngine.GenerateOne(); + ((GasolineEngine)((Car)chromeWheel1.Vehicle).Engine).Cylinders = _fakers.Cylinder.GenerateSet(2); - ChromeWheel chromeWheel2 = _fakers.ChromeWheel.Generate(); + ChromeWheel chromeWheel2 = _fakers.ChromeWheel.GenerateOne(); chromeWheel2.PaintColor = "blue"; - chromeWheel2.Vehicle = _fakers.Car.Generate(); - ((Car)chromeWheel2.Vehicle).Engine = _fakers.GasolineEngine.Generate(); - ((GasolineEngine)((Car)chromeWheel2.Vehicle).Engine).Cylinders = _fakers.Cylinder.Generate(1).ToHashSet(); + chromeWheel2.Vehicle = _fakers.Car.GenerateOne(); + ((Car)chromeWheel2.Vehicle).Engine = _fakers.GasolineEngine.GenerateOne(); + ((GasolineEngine)((Car)chromeWheel2.Vehicle).Engine).Cylinders = _fakers.Cylinder.GenerateSet(1); - ChromeWheel chromeWheel3 = _fakers.ChromeWheel.Generate(); + ChromeWheel chromeWheel3 = _fakers.ChromeWheel.GenerateOne(); chromeWheel3.PaintColor = "black"; - CarbonWheel carbonWheel1 = _fakers.CarbonWheel.Generate(); + CarbonWheel carbonWheel1 = _fakers.CarbonWheel.GenerateOne(); carbonWheel1.HasTube = false; - CarbonWheel carbonWheel2 = _fakers.CarbonWheel.Generate(); + CarbonWheel carbonWheel2 = _fakers.CarbonWheel.GenerateOne(); carbonWheel2.HasTube = true; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -2431,7 +2536,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(5); + responseDocument.Data.ManyValue.Should().HaveCount(5); responseDocument.Data.ManyValue[0].Type.Should().Be("chromeWheels"); responseDocument.Data.ManyValue[0].Id.Should().Be(chromeWheel3.StringId); @@ -2453,25 +2558,25 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_sort_on_derived_attribute_from_resource_definition_using_lambda_syntax() { // Arrange - ChromeWheel chromeWheel1 = _fakers.ChromeWheel.Generate(); + ChromeWheel chromeWheel1 = _fakers.ChromeWheel.GenerateOne(); chromeWheel1.PaintColor = "blue"; - chromeWheel1.Vehicle = _fakers.Car.Generate(); - ((Car)chromeWheel1.Vehicle).Engine = _fakers.GasolineEngine.Generate(); - ((GasolineEngine)((Car)chromeWheel1.Vehicle).Engine).Cylinders = _fakers.Cylinder.Generate(2).ToHashSet(); + chromeWheel1.Vehicle = _fakers.Car.GenerateOne(); + ((Car)chromeWheel1.Vehicle).Engine = _fakers.GasolineEngine.GenerateOne(); + ((GasolineEngine)((Car)chromeWheel1.Vehicle).Engine).Cylinders = _fakers.Cylinder.GenerateSet(2); - ChromeWheel chromeWheel2 = _fakers.ChromeWheel.Generate(); + ChromeWheel chromeWheel2 = _fakers.ChromeWheel.GenerateOne(); chromeWheel2.PaintColor = "blue"; - chromeWheel2.Vehicle = _fakers.Car.Generate(); - ((Car)chromeWheel2.Vehicle).Engine = _fakers.GasolineEngine.Generate(); - ((GasolineEngine)((Car)chromeWheel2.Vehicle).Engine).Cylinders = _fakers.Cylinder.Generate(1).ToHashSet(); + chromeWheel2.Vehicle = _fakers.Car.GenerateOne(); + ((Car)chromeWheel2.Vehicle).Engine = _fakers.GasolineEngine.GenerateOne(); + ((GasolineEngine)((Car)chromeWheel2.Vehicle).Engine).Cylinders = _fakers.Cylinder.GenerateSet(1); - ChromeWheel chromeWheel3 = _fakers.ChromeWheel.Generate(); + ChromeWheel chromeWheel3 = _fakers.ChromeWheel.GenerateOne(); chromeWheel3.PaintColor = "black"; - CarbonWheel carbonWheel1 = _fakers.CarbonWheel.Generate(); + CarbonWheel carbonWheel1 = _fakers.CarbonWheel.GenerateOne(); carbonWheel1.HasTube = false; - CarbonWheel carbonWheel2 = _fakers.CarbonWheel.Generate(); + CarbonWheel carbonWheel2 = _fakers.CarbonWheel.GenerateOne(); carbonWheel2.HasTube = true; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -2489,7 +2594,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(5); + responseDocument.Data.ManyValue.Should().HaveCount(5); responseDocument.Data.ManyValue[0].Type.Should().Be("chromeWheels"); responseDocument.Data.ManyValue[0].Id.Should().Be(chromeWheel3.StringId); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceWriteTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceWriteTests.cs index 0e55f5ad85..c3a1713947 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceWriteTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceWriteTests.cs @@ -75,7 +75,7 @@ protected ResourceInheritanceWriteTests(IntegrationTestContext>(); - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); - ChromeWheel existingChromeWheel = _fakers.ChromeWheel.Generate(); - Box existingBox = _fakers.Box.Generate(); - BicycleLight existingLight = _fakers.BicycleLight.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); + ChromeWheel existingChromeWheel = _fakers.ChromeWheel.GenerateOne(); + Box existingBox = _fakers.Box.GenerateOne(); + BicycleLight existingLight = _fakers.BicycleLight.GenerateOne(); - Bike newBike = _fakers.Bike.Generate(); + Bike newBike = _fakers.Bike.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -184,7 +184,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => } }; - const string route = "/vehicles"; + const string route = "/vehicles?include=manufacturer,wheels,engine,navigationSystem,features,sleepingArea,cargoBox,lights,foldingDimensions"; // Act (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync(route, requestBody); @@ -192,12 +192,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("bikes"); - responseDocument.Data.SingleValue.Attributes.ShouldOnlyContainKeys("weight", "requiresDriverLicense", "gearCount"); - responseDocument.Data.SingleValue.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights"); + responseDocument.Data.SingleValue.Attributes.Should().OnlyContainKeys("weight", "requiresDriverLicense", "gearCount"); + responseDocument.Data.SingleValue.Relationships.Should().OnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights"); - long newBikeId = long.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + long newBikeId = long.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -219,17 +219,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => bikeInDatabase.RequiresDriverLicense.Should().Be(newBike.RequiresDriverLicense); bikeInDatabase.GearCount.Should().Be(newBike.GearCount); - bikeInDatabase.Manufacturer.ShouldNotBeNull(); + bikeInDatabase.Manufacturer.Should().NotBeNull(); bikeInDatabase.Manufacturer.Id.Should().Be(existingManufacturer.Id); - bikeInDatabase.Wheels.ShouldHaveCount(1); + bikeInDatabase.Wheels.Should().HaveCount(1); bikeInDatabase.Wheels.ElementAt(0).Should().BeOfType(); bikeInDatabase.Wheels.ElementAt(0).Id.Should().Be(existingChromeWheel.Id); - bikeInDatabase.CargoBox.ShouldNotBeNull(); + bikeInDatabase.CargoBox.Should().NotBeNull(); bikeInDatabase.CargoBox.Id.Should().Be(existingBox.Id); - bikeInDatabase.Lights.ShouldHaveCount(1); + bikeInDatabase.Lights.Should().HaveCount(1); bikeInDatabase.Lights.ElementAt(0).Id.Should().Be(existingLight.Id); }); @@ -238,18 +238,18 @@ await _testContext.RunOnDatabaseAsync(async dbContext => } [Fact] - public async Task Can_create_concrete_derived_resource_at_abstract_endpoint_with_relationships() + public async Task Can_create_concrete_derived_resource_at_abstract_endpoint_with_relationships_and_includes() { // Arrange var carStore = _testContext.Factory.Services.GetRequiredService>(); - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); - CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.Generate(); - GasolineEngine existingGasolineEngine = _fakers.GasolineEngine.Generate(); - NavigationSystem existingNavigationSystem = _fakers.NavigationSystem.Generate(); - GenericFeature existingFeature = _fakers.GenericFeature.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); + CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.GenerateOne(); + GasolineEngine existingGasolineEngine = _fakers.GasolineEngine.GenerateOne(); + NavigationSystem existingNavigationSystem = _fakers.NavigationSystem.GenerateOne(); + GenericFeature existingFeature = _fakers.GenericFeature.GenerateOne(); - Car newCar = _fakers.Car.Generate(); + Car newCar = _fakers.Car.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -325,7 +325,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => } }; - const string route = "/vehicles"; + const string route = "/vehicles?include=manufacturer,wheels,engine,navigationSystem,features,sleepingArea,cargoBox,lights,foldingDimensions"; // Act (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync(route, requestBody); @@ -333,12 +333,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("cars"); - responseDocument.Data.SingleValue.Attributes.ShouldOnlyContainKeys("weight", "requiresDriverLicense", "licensePlate", "seatCount"); - responseDocument.Data.SingleValue.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "engine", "navigationSystem", "features"); + responseDocument.Data.SingleValue.Attributes.Should().OnlyContainKeys("weight", "requiresDriverLicense", "licensePlate", "seatCount"); + responseDocument.Data.SingleValue.Relationships.Should().OnlyContainKeys("manufacturer", "wheels", "engine", "navigationSystem", "features"); - long newCarId = long.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + long newCarId = long.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -362,21 +362,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => carInDatabase.LicensePlate.Should().Be(newCar.LicensePlate); carInDatabase.SeatCount.Should().Be(newCar.SeatCount); - carInDatabase.Manufacturer.ShouldNotBeNull(); + carInDatabase.Manufacturer.Should().NotBeNull(); carInDatabase.Manufacturer.Id.Should().Be(existingManufacturer.Id); - carInDatabase.Wheels.ShouldHaveCount(1); + carInDatabase.Wheels.Should().HaveCount(1); carInDatabase.Wheels.ElementAt(0).Should().BeOfType(); carInDatabase.Wheels.ElementAt(0).Id.Should().Be(existingCarbonWheel.Id); - carInDatabase.Engine.ShouldNotBeNull(); + carInDatabase.Engine.Should().NotBeNull(); carInDatabase.Engine.Should().BeOfType(); carInDatabase.Engine.Id.Should().Be(existingGasolineEngine.Id); - carInDatabase.NavigationSystem.ShouldNotBeNull(); + carInDatabase.NavigationSystem.Should().NotBeNull(); carInDatabase.NavigationSystem.Id.Should().Be(existingNavigationSystem.Id); - carInDatabase.Features.ShouldHaveCount(1); + carInDatabase.Features.Should().HaveCount(1); carInDatabase.Features.ElementAt(0).Id.Should().Be(existingFeature.Id); }); @@ -385,18 +385,18 @@ await _testContext.RunOnDatabaseAsync(async dbContext => } [Fact] - public async Task Can_create_concrete_derived_resource_at_concrete_base_endpoint_with_relationships() + public async Task Can_create_concrete_derived_resource_at_concrete_base_endpoint_with_relationships_and_includes() { // Arrange var tandemStore = _testContext.Factory.Services.GetRequiredService>(); - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); - ChromeWheel existingChromeWheel = _fakers.ChromeWheel.Generate(); - Box existingBox = _fakers.Box.Generate(); - BicycleLight existingLight = _fakers.BicycleLight.Generate(); - GenericFeature existingFeature = _fakers.GenericFeature.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); + ChromeWheel existingChromeWheel = _fakers.ChromeWheel.GenerateOne(); + Box existingBox = _fakers.Box.GenerateOne(); + BicycleLight existingLight = _fakers.BicycleLight.GenerateOne(); + GenericFeature existingFeature = _fakers.GenericFeature.GenerateOne(); - Tandem newTandem = _fakers.Tandem.Generate(); + Tandem newTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -475,7 +475,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => } }; - const string route = "/bikes"; + const string route = "/bikes?include=manufacturer,wheels,cargoBox,lights,foldingDimensions,features"; // Act (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync(route, requestBody); @@ -483,12 +483,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("tandems"); - responseDocument.Data.SingleValue.Attributes.ShouldOnlyContainKeys("weight", "requiresDriverLicense", "gearCount", "passengerCount"); - responseDocument.Data.SingleValue.Relationships.ShouldOnlyContainKeys("manufacturer", "wheels", "cargoBox", "lights", "features"); + responseDocument.Data.SingleValue.Attributes.Should().OnlyContainKeys("weight", "requiresDriverLicense", "gearCount", "passengerCount"); - long newTandemId = long.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + responseDocument.Data.SingleValue.Relationships.Should().OnlyContainKeys( + "manufacturer", "wheels", "cargoBox", "lights", "foldingDimensions", "features"); + + long newTandemId = long.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -512,20 +514,20 @@ await _testContext.RunOnDatabaseAsync(async dbContext => tandemInDatabase.GearCount.Should().Be(newTandem.GearCount); tandemInDatabase.PassengerCount.Should().Be(newTandem.PassengerCount); - tandemInDatabase.Manufacturer.ShouldNotBeNull(); + tandemInDatabase.Manufacturer.Should().NotBeNull(); tandemInDatabase.Manufacturer.Id.Should().Be(existingManufacturer.Id); - tandemInDatabase.Wheels.ShouldHaveCount(1); + tandemInDatabase.Wheels.Should().HaveCount(1); tandemInDatabase.Wheels.ElementAt(0).Should().BeOfType(); tandemInDatabase.Wheels.ElementAt(0).Id.Should().Be(existingChromeWheel.Id); - tandemInDatabase.CargoBox.ShouldNotBeNull(); + tandemInDatabase.CargoBox.Should().NotBeNull(); tandemInDatabase.CargoBox.Id.Should().Be(existingBox.Id); - tandemInDatabase.Lights.ShouldHaveCount(1); + tandemInDatabase.Lights.Should().HaveCount(1); tandemInDatabase.Lights.ElementAt(0).Id.Should().Be(existingLight.Id); - tandemInDatabase.Features.ShouldHaveCount(1); + tandemInDatabase.Features.Should().HaveCount(1); tandemInDatabase.Features.ElementAt(0).Id.Should().Be(existingFeature.Id); }); @@ -537,7 +539,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_concrete_base_resource_at_concrete_derived_endpoint() { // Arrange - Bike newBike = _fakers.Bike.Generate(); + Bike newBike = _fakers.Bike.GenerateOne(); var requestBody = new { @@ -561,13 +563,13 @@ public async Task Cannot_create_concrete_base_resource_at_concrete_derived_endpo // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Incompatible resource type found."); error.Detail.Should().Be("Type 'bikes' is not convertible to type 'tandems'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/type"); } @@ -575,7 +577,7 @@ public async Task Cannot_create_concrete_base_resource_at_concrete_derived_endpo public async Task Cannot_create_resource_with_abstract_relationship_type() { // Arrange - DieselEngine existingEngine = _fakers.DieselEngine.Generate(); + DieselEngine existingEngine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -610,85 +612,23 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Abstract resource type found."); error.Detail.Should().Be("Resource type 'engines' is abstract."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/engine/data/type"); } - [Fact] - public async Task Can_create_resource_with_concrete_base_relationship_type_stored_as_derived_type() - { - // Arrange - var carbonWheelStore = _testContext.Factory.Services.GetRequiredService>(); - - Tandem existingTandem = _fakers.Tandem.Generate(); - - await _testContext.RunOnDatabaseAsync(async dbContext => - { - dbContext.Vehicles.Add(existingTandem); - await dbContext.SaveChangesAsync(); - }); - - var requestBody = new - { - data = new - { - type = "carbonWheels", - relationships = new - { - vehicle = new - { - data = new - { - type = "bikes", - id = existingTandem.StringId - } - } - } - } - }; - - const string route = "/carbonWheels"; - - // Act - (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync(route, requestBody); - - // Assert - httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - - responseDocument.Data.SingleValue.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Type.Should().Be("carbonWheels"); - responseDocument.Data.SingleValue.Attributes.ShouldNotBeEmpty(); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); - - long newCarbonWheelId = long.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); - - await _testContext.RunOnDatabaseAsync(async dbContext => - { - CarbonWheel carbonWheelInDatabase = await dbContext.CarbonWheels.Include(wheel => wheel.Vehicle).FirstWithIdAsync(newCarbonWheelId); - - carbonWheelInDatabase.Should().BeOfType(); - carbonWheelInDatabase.Vehicle.ShouldNotBeNull(); - carbonWheelInDatabase.Vehicle.Should().BeOfType(); - carbonWheelInDatabase.Vehicle.Id.Should().Be(existingTandem.Id); - }); - - carbonWheelStore.AssertLeftType(); - carbonWheelStore.AssertRightTypes(typeof(Tandem)); - } - [Fact] public async Task Can_create_resource_with_concrete_base_ToOne_relationship_type_stored_as_derived_type_at_resource_endpoint() { // Arrange var carbonWheelStore = _testContext.Factory.Services.GetRequiredService>(); - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -723,19 +663,19 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("carbonWheels"); - responseDocument.Data.SingleValue.Attributes.ShouldNotBeEmpty(); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Attributes.Should().NotBeEmpty(); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); - long newCarbonWheelId = long.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + long newCarbonWheelId = long.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { CarbonWheel carbonWheelInDatabase = await dbContext.CarbonWheels.Include(wheel => wheel.Vehicle).FirstWithIdAsync(newCarbonWheelId); carbonWheelInDatabase.Should().BeOfType(); - carbonWheelInDatabase.Vehicle.ShouldNotBeNull(); + carbonWheelInDatabase.Vehicle.Should().NotBeNull(); carbonWheelInDatabase.Vehicle.Should().BeOfType(); carbonWheelInDatabase.Vehicle.Id.Should().Be(existingTandem.Id); }); @@ -750,7 +690,7 @@ public async Task Can_create_resource_with_concrete_base_ToMany_relationship_typ // Arrange var manufacturerStore = _testContext.Factory.Services.GetRequiredService>(); - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -788,19 +728,19 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("vehicleManufacturers"); - responseDocument.Data.SingleValue.Attributes.ShouldNotBeEmpty(); - responseDocument.Data.SingleValue.Relationships.ShouldNotBeEmpty(); + responseDocument.Data.SingleValue.Attributes.Should().NotBeEmpty(); + responseDocument.Data.SingleValue.Relationships.Should().NotBeEmpty(); - long newManufacturerId = long.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull()); + long newManufacturerId = long.Parse(responseDocument.Data.SingleValue.Id.Should().NotBeNull().And.Subject); await _testContext.RunOnDatabaseAsync(async dbContext => { VehicleManufacturer manufacturerInDatabase = await dbContext.VehicleManufacturers.Include(manufacturer => manufacturer.Vehicles) .FirstWithIdAsync(newManufacturerId); - manufacturerInDatabase.Vehicles.ShouldHaveCount(1); + manufacturerInDatabase.Vehicles.Should().HaveCount(1); manufacturerInDatabase.Vehicles.ElementAt(0).Should().BeOfType(); manufacturerInDatabase.Vehicles.ElementAt(0).Id.Should().Be(existingTandem.Id); }); @@ -813,7 +753,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_resource_with_concrete_derived_ToOne_relationship_type_stored_as_sibling_derived_type_at_resource_endpoint() { // Arrange - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -848,7 +788,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -861,8 +801,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_resource_with_concrete_derived_ToMany_relationship_type_stored_as_sibling_derived_type_at_resource_endpoint() { // Arrange - Truck existingTruck = _fakers.Truck.Generate(); - existingTruck.Engine = _fakers.DieselEngine.Generate(); + Truck existingTruck = _fakers.Truck.GenerateOne(); + existingTruck.Engine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -900,7 +840,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -942,7 +882,7 @@ public async Task Cannot_create_resource_with_unknown_resource_in_ToOne_relation // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -987,7 +927,7 @@ public async Task Cannot_create_resource_with_unknown_resources_in_ToMany_relati // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -1000,9 +940,9 @@ public async Task Cannot_create_resource_with_unknown_resources_in_ToMany_relati public async Task Cannot_update_abstract_resource_at_abstract_endpoint() { // Arrange - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); - int newPassengerCount = _fakers.Tandem.Generate().PassengerCount; + int newPassengerCount = _fakers.Tandem.GenerateOne().PassengerCount; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1031,29 +971,29 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Abstract resource type found."); error.Detail.Should().Be("Resource type 'vehicles' is abstract."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/type"); } [Fact] - public async Task Can_update_concrete_base_resource_at_abstract_endpoint_with_relationships() + public async Task Can_update_concrete_base_resource_at_abstract_endpoint_with_relationships_and_includes() { // Arrange var bikeStore = _testContext.Factory.Services.GetRequiredService>(); - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); - ChromeWheel existingChromeWheel = _fakers.ChromeWheel.Generate(); - Box existingBox = _fakers.Box.Generate(); - BicycleLight existingLight = _fakers.BicycleLight.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); + ChromeWheel existingChromeWheel = _fakers.ChromeWheel.GenerateOne(); + Box existingBox = _fakers.Box.GenerateOne(); + BicycleLight existingLight = _fakers.BicycleLight.GenerateOne(); - Bike existingBike = _fakers.Bike.Generate(); - Bike newBike = _fakers.Bike.Generate(); + Bike existingBike = _fakers.Bike.GenerateOne(); + Bike newBike = _fakers.Bike.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1121,7 +1061,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => } }; - string route = $"/vehicles/{existingBike.StringId}"; + string route = + $"/vehicles/{existingBike.StringId}?include=manufacturer,wheels,engine,navigationSystem,features,sleepingArea,cargoBox,lights,foldingDimensions"; // Act (HttpResponseMessage httpResponse, string responseDocument) = await _testContext.ExecutePatchAsync(route, requestBody); @@ -1151,17 +1092,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => bikeInDatabase.RequiresDriverLicense.Should().Be(newBike.RequiresDriverLicense); bikeInDatabase.GearCount.Should().Be(newBike.GearCount); - bikeInDatabase.Manufacturer.ShouldNotBeNull(); + bikeInDatabase.Manufacturer.Should().NotBeNull(); bikeInDatabase.Manufacturer.Id.Should().Be(existingManufacturer.Id); - bikeInDatabase.Wheels.ShouldHaveCount(1); + bikeInDatabase.Wheels.Should().HaveCount(1); bikeInDatabase.Wheels.ElementAt(0).Should().BeOfType(); bikeInDatabase.Wheels.ElementAt(0).Id.Should().Be(existingChromeWheel.Id); - bikeInDatabase.CargoBox.ShouldNotBeNull(); + bikeInDatabase.CargoBox.Should().NotBeNull(); bikeInDatabase.CargoBox.Id.Should().Be(existingBox.Id); - bikeInDatabase.Lights.ShouldHaveCount(1); + bikeInDatabase.Lights.Should().HaveCount(1); bikeInDatabase.Lights.ElementAt(0).Id.Should().Be(existingLight.Id); }); @@ -1170,18 +1111,18 @@ await _testContext.RunOnDatabaseAsync(async dbContext => } [Fact] - public async Task Can_update_concrete_base_resource_stored_as_concrete_derived_at_abstract_endpoint_with_relationships() + public async Task Can_update_concrete_base_resource_stored_as_concrete_derived_at_abstract_endpoint_with_relationships_and_includes() { // Arrange var tandemStore = _testContext.Factory.Services.GetRequiredService>(); - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); - ChromeWheel existingChromeWheel = _fakers.ChromeWheel.Generate(); - Box existingBox = _fakers.Box.Generate(); - BicycleLight existingLight = _fakers.BicycleLight.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); + ChromeWheel existingChromeWheel = _fakers.ChromeWheel.GenerateOne(); + Box existingBox = _fakers.Box.GenerateOne(); + BicycleLight existingLight = _fakers.BicycleLight.GenerateOne(); - Tandem existingTandem = _fakers.Tandem.Generate(); - Bike newBike = _fakers.Bike.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); + Bike newBike = _fakers.Bike.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1249,7 +1190,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => } }; - string route = $"/vehicles/{existingTandem.StringId}"; + string route = + $"/vehicles/{existingTandem.StringId}?include=manufacturer,wheels,engine,navigationSystem,features,sleepingArea,cargoBox,lights,foldingDimensions"; // Act (HttpResponseMessage httpResponse, string responseDocument) = await _testContext.ExecutePatchAsync(route, requestBody); @@ -1279,17 +1221,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => tandemInDatabase.RequiresDriverLicense.Should().Be(newBike.RequiresDriverLicense); tandemInDatabase.GearCount.Should().Be(newBike.GearCount); - tandemInDatabase.Manufacturer.ShouldNotBeNull(); + tandemInDatabase.Manufacturer.Should().NotBeNull(); tandemInDatabase.Manufacturer.Id.Should().Be(existingManufacturer.Id); - tandemInDatabase.Wheels.ShouldHaveCount(1); + tandemInDatabase.Wheels.Should().HaveCount(1); tandemInDatabase.Wheels.ElementAt(0).Should().BeOfType(); tandemInDatabase.Wheels.ElementAt(0).Id.Should().Be(existingChromeWheel.Id); - tandemInDatabase.CargoBox.ShouldNotBeNull(); + tandemInDatabase.CargoBox.Should().NotBeNull(); tandemInDatabase.CargoBox.Id.Should().Be(existingBox.Id); - tandemInDatabase.Lights.ShouldHaveCount(1); + tandemInDatabase.Lights.Should().HaveCount(1); tandemInDatabase.Lights.ElementAt(0).Id.Should().Be(existingLight.Id); }); @@ -1301,9 +1243,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_concrete_base_resource_at_concrete_derived_endpoint() { // Arrange - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); - int newPassengerCount = _fakers.Tandem.Generate().PassengerCount; + int newPassengerCount = _fakers.Tandem.GenerateOne().PassengerCount; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1332,13 +1274,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Conflict); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Conflict); error.Title.Should().Be("Failed to deserialize request body: Incompatible resource type found."); error.Detail.Should().Be("Type 'bikes' is not convertible to type 'tandems'."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/type"); } @@ -1346,10 +1288,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_abstract_relationship_type() { // Arrange - Truck existingTruck = _fakers.Truck.Generate(); - existingTruck.Engine = _fakers.GasolineEngine.Generate(); + Truck existingTruck = _fakers.Truck.GenerateOne(); + existingTruck.Engine = _fakers.GasolineEngine.GenerateOne(); - DieselEngine existingEngine = _fakers.DieselEngine.Generate(); + DieselEngine existingEngine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1386,13 +1328,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.UnprocessableEntity); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); error.Title.Should().Be("Failed to deserialize request body: Abstract resource type found."); error.Detail.Should().Be("Resource type 'engines' is abstract."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Pointer.Should().Be("/data/relationships/engine/data/type"); } @@ -1402,9 +1344,9 @@ public async Task Can_update_resource_with_concrete_base_ToOne_relationship_type // Arrange var carbonWheelStore = _testContext.Factory.Services.GetRequiredService>(); - CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.Generate(); + CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.GenerateOne(); - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1448,7 +1390,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => CarbonWheel carbonWheelInDatabase = await dbContext.CarbonWheels.Include(wheel => wheel.Vehicle).FirstWithIdAsync(existingCarbonWheel.Id); carbonWheelInDatabase.Should().BeOfType(); - carbonWheelInDatabase.Vehicle.ShouldNotBeNull(); + carbonWheelInDatabase.Vehicle.Should().NotBeNull(); carbonWheelInDatabase.Vehicle.Should().BeOfType(); carbonWheelInDatabase.Vehicle.Id.Should().Be(existingTandem.Id); }); @@ -1463,9 +1405,9 @@ public async Task Can_update_resource_with_concrete_base_ToMany_relationship_typ // Arrange var manufacturerStore = _testContext.Factory.Services.GetRequiredService>(); - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1512,7 +1454,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => VehicleManufacturer manufacturerInDatabase = await dbContext.VehicleManufacturers.Include(manufacturer => manufacturer.Vehicles) .FirstWithIdAsync(existingManufacturer.Id); - manufacturerInDatabase.Vehicles.ShouldHaveCount(1); + manufacturerInDatabase.Vehicles.Should().HaveCount(1); manufacturerInDatabase.Vehicles.ElementAt(0).Should().BeOfType(); manufacturerInDatabase.Vehicles.ElementAt(0).Id.Should().Be(existingTandem.Id); }); @@ -1525,9 +1467,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_concrete_derived_ToOne_relationship_type_stored_as_sibling_derived_type_at_resource_endpoint() { // Arrange - CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.Generate(); + CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.GenerateOne(); - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1564,7 +1506,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -1577,10 +1519,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_concrete_derived_ToMany_relationship_type_stored_as_sibling_derived_type_at_resource_endpoint() { // Arrange - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); - Truck existingTruck = _fakers.Truck.Generate(); - existingTruck.Engine = _fakers.DieselEngine.Generate(); + Truck existingTruck = _fakers.Truck.GenerateOne(); + existingTruck.Engine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1620,7 +1562,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -1633,7 +1575,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_unknown_resource_in_ToOne_relationship_at_resource_endpoint() { // Arrange - CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.Generate(); + CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.GenerateOne(); string unknownTruckId = Unknown.StringId.For(); @@ -1671,7 +1613,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -1684,7 +1626,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_unknown_resources_in_ToMany_relationship_at_resource_endpoint() { // Arrange - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); string unknownTruckId = Unknown.StringId.For(); @@ -1725,7 +1667,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -1740,7 +1682,7 @@ public async Task Can_delete_resource_stored_as_concrete_derived_at_abstract_end // Arrange var tandemStore = _testContext.Factory.Services.GetRequiredService>(); - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1766,14 +1708,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }); tandemStore.AssertLeftType(); - tandemStore.AssertRightTypes([]); + tandemStore.AssertRightTypes(); } [Fact] public async Task Cannot_delete_concrete_base_resource_at_concrete_derived_endpoint() { // Arrange - Bike existingBike = _fakers.Bike.Generate(); + Bike existingBike = _fakers.Bike.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1789,7 +1731,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -1804,9 +1746,9 @@ public async Task Can_set_abstract_resource_at_abstract_ToOne_relationship_endpo // Arrange var carbonWheelStore = _testContext.Factory.Services.GetRequiredService>(); - CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.Generate(); + CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.GenerateOne(); - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1840,7 +1782,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => wheelInDatabase.Should().BeOfType(); - wheelInDatabase.Vehicle.ShouldNotBeNull(); + wheelInDatabase.Vehicle.Should().NotBeNull(); wheelInDatabase.Vehicle.Should().BeOfType(); wheelInDatabase.Vehicle.Id.Should().Be(existingTandem.Id); }); @@ -1855,9 +1797,9 @@ public async Task Can_set_abstract_resources_at_abstract_ToMany_relationship_end // Arrange var tandemStore = _testContext.Factory.Services.GetRequiredService>(); - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); - ChromeWheel existingChromeWheel = _fakers.ChromeWheel.Generate(); + ChromeWheel existingChromeWheel = _fakers.ChromeWheel.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1894,7 +1836,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => vehicleInDatabase.Should().BeOfType(); - vehicleInDatabase.Wheels.ShouldHaveCount(1); + vehicleInDatabase.Wheels.Should().HaveCount(1); vehicleInDatabase.Wheels.ElementAt(0).Should().BeOfType(); vehicleInDatabase.Wheels.ElementAt(0).Id.Should().Be(existingChromeWheel.Id); }); @@ -1909,9 +1851,9 @@ public async Task Can_set_concrete_base_resource_stored_as_derived_at_abstract_T // Arrange var carbonWheelStore = _testContext.Factory.Services.GetRequiredService>(); - CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.Generate(); + CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.GenerateOne(); - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1945,7 +1887,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => wheelInDatabase.Should().BeOfType(); - wheelInDatabase.Vehicle.ShouldNotBeNull(); + wheelInDatabase.Vehicle.Should().NotBeNull(); wheelInDatabase.Vehicle.Should().BeOfType(); wheelInDatabase.Vehicle.Id.Should().Be(existingTandem.Id); }); @@ -1960,9 +1902,9 @@ public async Task Can_set_concrete_base_resources_stored_as_derived_at_ToMany_re // Arrange var manufacturerStore = _testContext.Factory.Services.GetRequiredService>(); - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1998,7 +1940,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => VehicleManufacturer manufacturerInDatabase = await dbContext.VehicleManufacturers.Include(manufacturer => manufacturer.Vehicles) .FirstWithIdAsync(existingManufacturer.Id); - manufacturerInDatabase.Vehicles.ShouldHaveCount(1); + manufacturerInDatabase.Vehicles.Should().HaveCount(1); manufacturerInDatabase.Vehicles.ElementAt(0).Should().BeOfType(); manufacturerInDatabase.Vehicles.ElementAt(0).Id.Should().Be(existingTandem.Id); }); @@ -2011,9 +1953,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_set_concrete_derived_resource_stored_as_concrete_base_at_abstract_ToOne_relationship_endpoint() { // Arrange - CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.Generate(); + CarbonWheel existingCarbonWheel = _fakers.CarbonWheel.GenerateOne(); - Bike existingBike = _fakers.Bike.Generate(); + Bike existingBike = _fakers.Bike.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2039,7 +1981,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -2052,10 +1994,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_set_concrete_derived_resources_stored_as_sibling_derived_at_ToMany_relationship_endpoint() { // Arrange - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); - Truck existingTruck = _fakers.Truck.Generate(); - existingTruck.Engine = _fakers.DieselEngine.Generate(); + Truck existingTruck = _fakers.Truck.GenerateOne(); + existingTruck.Engine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2084,7 +2026,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -2097,7 +2039,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_set_unknown_resources_at_ToMany_relationship_endpoint() { // Arrange - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); string unknownTruckId = Unknown.StringId.For(); @@ -2127,7 +2069,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -2139,8 +2081,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => [Fact] public async Task Cannot_clear_ToOne_relationship_for_left_type_stored_as_sibling_type() { - Truck existingTruck = _fakers.Truck.Generate(); - existingTruck.Engine = _fakers.DieselEngine.Generate(); + Truck existingTruck = _fakers.Truck.GenerateOne(); + existingTruck.Engine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2161,7 +2103,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -2176,10 +2118,10 @@ public async Task Can_add_abstract_resources_at_abstract_ToMany_relationship_end // Arrange var tandemStore = _testContext.Factory.Services.GetRequiredService>(); - Tandem existingTandem = _fakers.Tandem.Generate(); - existingTandem.Wheels = _fakers.CarbonWheel.Generate(1).Cast().ToHashSet(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); + existingTandem.Wheels = _fakers.CarbonWheel.GenerateSet(1); - ChromeWheel existingChromeWheel = _fakers.ChromeWheel.Generate(); + ChromeWheel existingChromeWheel = _fakers.ChromeWheel.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2216,7 +2158,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => vehicleInDatabase.Should().BeOfType(); - vehicleInDatabase.Wheels.ShouldHaveCount(2); + vehicleInDatabase.Wheels.Should().HaveCount(2); vehicleInDatabase.Wheels.ElementAt(0).Should().BeOfType(); vehicleInDatabase.Wheels.ElementAt(0).Id.Should().Be(existingTandem.Wheels.ElementAt(0).Id); vehicleInDatabase.Wheels.ElementAt(1).Should().BeOfType(); @@ -2233,10 +2175,10 @@ public async Task Can_add_concrete_derived_resources_at_abstract_ToMany_relation // Arrange var tandemStore = _testContext.Factory.Services.GetRequiredService>(); - Tandem existingTandem = _fakers.Tandem.Generate(); - existingTandem.Wheels = _fakers.CarbonWheel.Generate(1).Cast().ToHashSet(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); + existingTandem.Wheels = _fakers.CarbonWheel.GenerateSet(1); - ChromeWheel existingChromeWheel = _fakers.ChromeWheel.Generate(); + ChromeWheel existingChromeWheel = _fakers.ChromeWheel.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2273,7 +2215,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => vehicleInDatabase.Should().BeOfType(); - vehicleInDatabase.Wheels.ShouldHaveCount(2); + vehicleInDatabase.Wheels.Should().HaveCount(2); vehicleInDatabase.Wheels.ElementAt(0).Should().BeOfType(); vehicleInDatabase.Wheels.ElementAt(0).Id.Should().Be(existingTandem.Wheels.ElementAt(0).Id); vehicleInDatabase.Wheels.ElementAt(1).Should().BeOfType(); @@ -2290,11 +2232,11 @@ public async Task Can_add_concrete_base_resources_stored_as_derived_at_ToMany_re // Arrange var manufacturerStore = _testContext.Factory.Services.GetRequiredService>(); - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); - existingManufacturer.Vehicles = _fakers.Car.Generate(1).Cast().ToHashSet(); - ((Car)existingManufacturer.Vehicles.ElementAt(0)).Engine = _fakers.GasolineEngine.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); + existingManufacturer.Vehicles = _fakers.Car.GenerateSet(1); + ((Car)existingManufacturer.Vehicles.ElementAt(0)).Engine = _fakers.GasolineEngine.GenerateOne(); - Tandem existingTandem = _fakers.Tandem.Generate(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2337,7 +2279,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // @formatter:wrap_after_property_in_chained_method_calls restore // @formatter:wrap_chained_method_calls restore - manufacturerInDatabase.Vehicles.ShouldHaveCount(2); + manufacturerInDatabase.Vehicles.Should().HaveCount(2); manufacturerInDatabase.Vehicles.ElementAt(0).Should().BeOfType(); manufacturerInDatabase.Vehicles.ElementAt(0).Id.Should().Be(existingManufacturer.Vehicles.ElementAt(0).Id); manufacturerInDatabase.Vehicles.ElementAt(1).Should().BeOfType(); @@ -2352,9 +2294,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_concrete_derived_resources_stored_as_sibling_derived_at_abstract_ToMany_relationship_endpoint() { // Arrange - Bike existingBike = _fakers.Bike.Generate(); + Bike existingBike = _fakers.Bike.GenerateOne(); - ChromeWheel existingChromeWheel = _fakers.ChromeWheel.Generate(); + ChromeWheel existingChromeWheel = _fakers.ChromeWheel.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2383,7 +2325,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -2396,7 +2338,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_unknown_resources_at_ToMany_relationship_endpoint() { // Arrange - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); string unknownTruckId = Unknown.StringId.For(); @@ -2426,7 +2368,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -2438,8 +2380,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => [Fact] public async Task Cannot_add_to_ToMany_relationship_for_left_type_stored_as_sibling_type() { - Truck existingTruck = _fakers.Truck.Generate(); - existingTruck.Engine = _fakers.DieselEngine.Generate(); + Truck existingTruck = _fakers.Truck.GenerateOne(); + existingTruck.Engine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2460,7 +2402,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -2475,8 +2417,8 @@ public async Task Can_remove_abstract_resources_at_abstract_ToMany_relationship_ // Arrange var tandemStore = _testContext.Factory.Services.GetRequiredService>(); - Tandem existingTandem = _fakers.Tandem.Generate(); - existingTandem.Wheels = _fakers.ChromeWheel.Generate(2).Cast().ToHashSet(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); + existingTandem.Wheels = _fakers.ChromeWheel.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2512,7 +2454,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => vehicleInDatabase.Should().BeOfType(); - vehicleInDatabase.Wheels.ShouldHaveCount(1); + vehicleInDatabase.Wheels.Should().HaveCount(1); vehicleInDatabase.Wheels.ElementAt(0).Should().BeOfType(); vehicleInDatabase.Wheels.ElementAt(0).Id.Should().Be(existingTandem.Wheels.ElementAt(1).Id); }); @@ -2527,8 +2469,8 @@ public async Task Can_remove_concrete_derived_resources_at_abstract_ToMany_relat // Arrange var tandemStore = _testContext.Factory.Services.GetRequiredService>(); - Tandem existingTandem = _fakers.Tandem.Generate(); - existingTandem.Wheels = _fakers.ChromeWheel.Generate(2).Cast().ToHashSet(); + Tandem existingTandem = _fakers.Tandem.GenerateOne(); + existingTandem.Wheels = _fakers.ChromeWheel.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2564,7 +2506,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => vehicleInDatabase.Should().BeOfType(); - vehicleInDatabase.Wheels.ShouldHaveCount(1); + vehicleInDatabase.Wheels.Should().HaveCount(1); vehicleInDatabase.Wheels.ElementAt(0).Should().BeOfType(); vehicleInDatabase.Wheels.ElementAt(0).Id.Should().Be(existingTandem.Wheels.ElementAt(1).Id); }); @@ -2579,9 +2521,9 @@ public async Task Can_remove_concrete_base_resources_stored_as_derived_at_ToMany // Arrange var manufacturerStore = _testContext.Factory.Services.GetRequiredService>(); - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); - existingManufacturer.Vehicles = _fakers.Tandem.Generate(1).Cast().Concat(_fakers.Car.Generate(1)).ToHashSet(); - ((Car)existingManufacturer.Vehicles.ElementAt(1)).Engine = _fakers.GasolineEngine.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); + existingManufacturer.Vehicles = _fakers.Tandem.GenerateSet(1).Concat(_fakers.Car.GenerateSet(1)).ToHashSet(); + ((Car)existingManufacturer.Vehicles.ElementAt(1)).Engine = _fakers.GasolineEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2616,7 +2558,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => VehicleManufacturer manufacturerInDatabase = await dbContext.VehicleManufacturers.Include(manufacturer => manufacturer.Vehicles) .FirstWithIdAsync(existingManufacturer.Id); - manufacturerInDatabase.Vehicles.ShouldHaveCount(1); + manufacturerInDatabase.Vehicles.Should().HaveCount(1); manufacturerInDatabase.Vehicles.ElementAt(0).Should().BeOfType(); manufacturerInDatabase.Vehicles.ElementAt(0).Id.Should().Be(existingManufacturer.Vehicles.ElementAt(1).Id); }); @@ -2629,8 +2571,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_concrete_derived_resources_stored_as_sibling_derived_at_abstract_ToMany_relationship_endpoint() { // Arrange - Bike existingBike = _fakers.Bike.Generate(); - existingBike.Wheels = _fakers.ChromeWheel.Generate(2).Cast().ToHashSet(); + Bike existingBike = _fakers.Bike.GenerateOne(); + existingBike.Wheels = _fakers.ChromeWheel.GenerateSet(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2658,7 +2600,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); string? chromeWheelId = existingBike.Wheels.ElementAt(0).StringId; @@ -2673,7 +2615,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_unknown_resources_at_ToMany_relationship_endpoint() { // Arrange - VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.Generate(); + VehicleManufacturer existingManufacturer = _fakers.VehicleManufacturer.GenerateOne(); string unknownTruckId = Unknown.StringId.For(); @@ -2703,7 +2645,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -2715,8 +2657,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => [Fact] public async Task Cannot_remove_from_ToMany_relationship_for_left_type_stored_as_sibling_type() { - Truck existingTruck = _fakers.Truck.Generate(); - existingTruck.Engine = _fakers.DieselEngine.Generate(); + Truck existingTruck = _fakers.Truck.GenerateOne(); + existingTruck.Engine = _fakers.DieselEngine.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -2737,7 +2679,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceTypeCaptureStore.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceTypeCaptureStore.cs index d9ac30f8c0..355b779779 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceTypeCaptureStore.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceTypeCaptureStore.cs @@ -2,7 +2,6 @@ using FluentAssertions; using JsonApiDotNetCore.Middleware; -using TestBuildingBlocks; namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance; @@ -10,8 +9,8 @@ public sealed class ResourceTypeCaptureStore { internal Type? LeftDeclaredType { get; set; } internal string? LeftReflectedTypeName { get; set; } - internal ISet RightTypeNames { get; } = new HashSet(); - internal IJsonApiRequest? Request { get; set; } + internal HashSet RightTypeNames { get; } = []; + internal JsonApiRequest? Request { get; set; } internal void Reset() { @@ -23,18 +22,18 @@ internal void Reset() internal void AssertLeftType() { - LeftDeclaredType.Should().Be(typeof(TLeft)); + LeftDeclaredType.Should().Be(); LeftReflectedTypeName.Should().Be(typeof(TLeft).Name); - Request.ShouldNotBeNull(); - Request.PrimaryResourceType.ShouldNotBeNull(); - Request.PrimaryResourceType.ClrType.Should().Be(typeof(TLeft)); - Request.Relationship?.LeftType.ClrType.Should().Be(typeof(TLeft)); + Request.Should().NotBeNull(); + Request.PrimaryResourceType.Should().NotBeNull(); + Request.PrimaryResourceType.ClrType.Should().Be(); + Request.Relationship?.LeftType.ClrType.Should().Be(); } internal void AssertRightTypes(params Type[] types) { - RightTypeNames.ShouldHaveCount(types.Length); + RightTypeNames.Should().HaveCount(types.Length); foreach (Type type in types) { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceTypeCapturingDefinition.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceTypeCapturingDefinition.cs index 8e9a49dbfc..c12cf527b2 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceTypeCapturingDefinition.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceTypeCapturingDefinition.cs @@ -1,5 +1,4 @@ using JetBrains.Annotations; -using JsonApiDotNetCore; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Middleware; using JsonApiDotNetCore.Resources; @@ -20,8 +19,8 @@ public sealed class ResourceTypeCapturingDefinition : JsonApiRes public ResourceTypeCapturingDefinition(IResourceGraph resourceGraph, IJsonApiRequest request, ResourceTypeCaptureStore captureStore) : base(resourceGraph) { - ArgumentGuard.NotNull(request); - ArgumentGuard.NotNull(captureStore); + ArgumentNullException.ThrowIfNull(request); + ArgumentNullException.ThrowIfNull(captureStore); _request = request; _captureStore = captureStore; @@ -110,7 +109,7 @@ private void EnsureSnapshot(TResource leftType, IEnumerable right } } - private IJsonApiRequest TakeRequestSnapshot() + private JsonApiRequest TakeRequestSnapshot() { var requestSnapshot = new JsonApiRequest(); requestSnapshot.CopyFrom(_request); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerConcreteType/TablePerConcreteTypeDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerConcreteType/TablePerConcreteTypeDbContext.cs index 1e7e644367..9da35f2eed 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerConcreteType/TablePerConcreteTypeDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerConcreteType/TablePerConcreteTypeDbContext.cs @@ -7,7 +7,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance.TablePerConcreteType; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class TablePerConcreteTypeDbContext(DbContextOptions options) : ResourceInheritanceDbContext(options) +public sealed class TablePerConcreteTypeDbContext(DbContextOptions options) + : ResourceInheritanceDbContext(options) { protected override void OnModelCreating(ModelBuilder builder) { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerHierarchy/TablePerHierarchyDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerHierarchy/TablePerHierarchyDbContext.cs index f9d63e7dde..38ce305787 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerHierarchy/TablePerHierarchyDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerHierarchy/TablePerHierarchyDbContext.cs @@ -4,4 +4,5 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance.TablePerHierarchy; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class TablePerHierarchyDbContext(DbContextOptions options) : ResourceInheritanceDbContext(options); +public sealed class TablePerHierarchyDbContext(DbContextOptions options) + : ResourceInheritanceDbContext(options); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerType/TablePerTypeDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerType/TablePerTypeDbContext.cs index 382a54cc3e..d31cc6a5b6 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerType/TablePerTypeDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerType/TablePerTypeDbContext.cs @@ -7,7 +7,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance.TablePerType; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class TablePerTypeDbContext(DbContextOptions options) : ResourceInheritanceDbContext(options) +public sealed class TablePerTypeDbContext(DbContextOptions options) + : ResourceInheritanceDbContext(options) { protected override void OnModelCreating(ModelBuilder builder) { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/WheelSortDefinition.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/WheelSortDefinition.cs index 7785622e9e..98b3e0cdaa 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/WheelSortDefinition.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/WheelSortDefinition.cs @@ -1,7 +1,6 @@ using System.Collections.Immutable; using System.ComponentModel; using JetBrains.Annotations; -using JsonApiDotNetCore; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Queries.Expressions; using JsonApiDotNetCore.Resources; @@ -19,7 +18,7 @@ public sealed class WheelSortDefinition : JsonApiResourceDefinition public WheelSortDefinition(IResourceGraph resourceGraph, IHttpContextAccessor httpContextAccessor) : base(resourceGraph) { - ArgumentGuard.NotNull(httpContextAccessor); + ArgumentNullException.ThrowIfNull(httpContextAccessor); _httpContextAccessor = httpContextAccessor; } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/DisableQueryStringTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/DisableQueryStringTests.cs index 22044421e2..5415d79f14 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/DisableQueryStringTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/DisableQueryStringTests.cs @@ -38,13 +38,13 @@ public async Task Cannot_sort_if_query_string_parameter_is_blocked_by_controller // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Usage of one or more query string parameters is not allowed at the requested endpoint."); error.Detail.Should().Be("The parameter 'sort' cannot be used at this endpoint."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("sort"); } @@ -60,13 +60,13 @@ public async Task Cannot_paginate_if_query_string_parameter_is_blocked_by_contro // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Usage of one or more query string parameters is not allowed at the requested endpoint."); error.Detail.Should().Be("The parameter 'page[number]' cannot be used at this endpoint."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("page[number]"); } @@ -82,7 +82,7 @@ public async Task Can_use_custom_query_string_parameter() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.ShouldNotBeEmpty(); + responseDocument.Should().NotBeEmpty(); } [Fact] @@ -97,13 +97,13 @@ public async Task Cannot_use_custom_query_string_parameter_if_blocked_by_control // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.BadRequest); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("Usage of one or more query string parameters is not allowed at the requested endpoint."); error.Detail.Should().Be("The parameter 'skipCache' cannot be used at this endpoint."); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("skipCache"); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/EndpointFilterTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/EndpointFilterTests.cs new file mode 100644 index 0000000000..87289ab555 --- /dev/null +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/EndpointFilterTests.cs @@ -0,0 +1,61 @@ +using System.Net; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; +using Microsoft.Extensions.DependencyInjection; +using TestBuildingBlocks; +using Xunit; + +namespace JsonApiDotNetCoreTests.IntegrationTests.RestrictedControllers; + +public sealed class EndpointFilterTests : IClassFixture, RestrictionDbContext>> +{ + private readonly IntegrationTestContext, RestrictionDbContext> _testContext; + private readonly RestrictionFakers _fakers = new(); + + public EndpointFilterTests(IntegrationTestContext, RestrictionDbContext> testContext) + { + _testContext = testContext; + + testContext.UseController(); + + testContext.ConfigureServices(services => services.AddSingleton()); + } + + [Fact] + public async Task Cannot_get_relationship() + { + // Arrange + Bed bed = _fakers.Bed.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Beds.Add(bed); + await dbContext.SaveChangesAsync(); + }); + + string route = $"/beds/{bed.StringId}/relationships/pillows"; + + // Act + (HttpResponseMessage httpResponse, _) = await _testContext.ExecuteGetAsync(route); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); + } + + private sealed class NoRelationshipsAtBedJsonApiEndpointFilter : IJsonApiEndpointFilter + { + public bool IsEnabled(ResourceType resourceType, JsonApiEndpoints endpoint) + { + return !IsGetRelationshipAtBed(endpoint, resourceType); + } + + private static bool IsGetRelationshipAtBed(JsonApiEndpoints endpoint, ResourceType resourceType) + { + bool isRelationshipEndpoint = endpoint is JsonApiEndpoints.GetRelationship or JsonApiEndpoints.PostRelationship or + JsonApiEndpoints.PatchRelationship or JsonApiEndpoints.DeleteRelationship; + + return isRelationshipEndpoint && resourceType.ClrType == typeof(Bed); + } + } +} diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/NoRelationshipsControllerTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/NoRelationshipsControllerTests.cs index 89e5c20741..b5453c6112 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/NoRelationshipsControllerTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/NoRelationshipsControllerTests.cs @@ -35,7 +35,7 @@ public async Task Can_get_resources() public async Task Can_get_resource() { // Arrange - Chair chair = _fakers.Chair.Generate(); + Chair chair = _fakers.Chair.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -56,7 +56,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resources() { // Arrange - Chair chair = _fakers.Chair.Generate(); + Chair chair = _fakers.Chair.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -72,7 +72,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); @@ -84,7 +84,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resource() { // Arrange - Chair chair = _fakers.Chair.Generate(); + Chair chair = _fakers.Chair.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -100,7 +100,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); @@ -112,7 +112,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_relationship() { // Arrange - Chair chair = _fakers.Chair.Generate(); + Chair chair = _fakers.Chair.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -128,7 +128,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); @@ -164,7 +164,7 @@ public async Task Can_create_resource() public async Task Can_update_resource() { // Arrange - Chair existingChair = _fakers.Chair.Generate(); + Chair existingChair = _fakers.Chair.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -197,7 +197,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource() { // Arrange - Chair existingChair = _fakers.Chair.Generate(); + Chair existingChair = _fakers.Chair.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -218,7 +218,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_relationship() { // Arrange - Chair existingChair = _fakers.Chair.Generate(); + Chair existingChair = _fakers.Chair.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -239,7 +239,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); @@ -251,7 +251,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_to_ToMany_relationship() { // Arrange - Chair existingChair = _fakers.Chair.Generate(); + Chair existingChair = _fakers.Chair.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -272,7 +272,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); @@ -284,7 +284,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_from_ToMany_relationship() { // Arrange - Chair existingChair = _fakers.Chair.Generate(); + Chair existingChair = _fakers.Chair.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -305,7 +305,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/ReadOnlyControllerTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/ReadOnlyControllerTests.cs index 37900089db..bacdab9e6f 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/ReadOnlyControllerTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/ReadOnlyControllerTests.cs @@ -35,7 +35,7 @@ public async Task Can_get_resources() public async Task Can_get_resource() { // Arrange - Bed bed = _fakers.Bed.Generate(); + Bed bed = _fakers.Bed.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -56,7 +56,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_secondary_resources() { // Arrange - Bed bed = _fakers.Bed.Generate(); + Bed bed = _fakers.Bed.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -77,7 +77,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_secondary_resource() { // Arrange - Bed bed = _fakers.Bed.Generate(); + Bed bed = _fakers.Bed.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -98,7 +98,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_relationship() { // Arrange - Bed bed = _fakers.Bed.Generate(); + Bed bed = _fakers.Bed.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -138,7 +138,7 @@ public async Task Cannot_create_resource() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); @@ -150,7 +150,7 @@ public async Task Cannot_create_resource() public async Task Cannot_update_resource() { // Arrange - Bed existingBed = _fakers.Bed.Generate(); + Bed existingBed = _fakers.Bed.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -178,7 +178,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); @@ -190,7 +190,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_delete_resource() { // Arrange - Bed existingBed = _fakers.Bed.Generate(); + Bed existingBed = _fakers.Bed.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -206,7 +206,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); @@ -218,7 +218,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_relationship() { // Arrange - Bed existingBed = _fakers.Bed.Generate(); + Bed existingBed = _fakers.Bed.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -239,7 +239,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); @@ -251,7 +251,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_to_ToMany_relationship() { // Arrange - Bed existingBed = _fakers.Bed.Generate(); + Bed existingBed = _fakers.Bed.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -272,7 +272,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); @@ -284,7 +284,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_from_ToMany_relationship() { // Arrange - Bed existingBed = _fakers.Bed.Generate(); + Bed existingBed = _fakers.Bed.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -305,7 +305,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/RestrictionDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/RestrictionDbContext.cs index 8a5f5484de..d83e096e6a 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/RestrictionDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/RestrictionDbContext.cs @@ -5,7 +5,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.RestrictedControllers; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class RestrictionDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class RestrictionDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet Tables => Set
(); public DbSet Chairs => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/WriteOnlyControllerTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/WriteOnlyControllerTests.cs index 7a3f42accf..a9c35de96f 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/WriteOnlyControllerTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/WriteOnlyControllerTests.cs @@ -30,7 +30,7 @@ public async Task Cannot_get_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); @@ -42,7 +42,7 @@ public async Task Cannot_get_resources() public async Task Cannot_get_resource() { // Arrange - Table table = _fakers.Table.Generate(); + Table table = _fakers.Table.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -58,7 +58,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); @@ -70,7 +70,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resources() { // Arrange - Table table = _fakers.Table.Generate(); + Table table = _fakers.Table.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -86,7 +86,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); @@ -98,7 +98,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resource() { // Arrange - Table table = _fakers.Table.Generate(); + Table table = _fakers.Table.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -114,7 +114,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); @@ -126,7 +126,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_relationship() { // Arrange - Table table = _fakers.Table.Generate(); + Table table = _fakers.Table.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -142,7 +142,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Forbidden); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.Forbidden); @@ -178,7 +178,7 @@ public async Task Can_create_resource() public async Task Can_update_resource() { // Arrange - Table existingTable = _fakers.Table.Generate(); + Table existingTable = _fakers.Table.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -211,7 +211,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource() { // Arrange - Table existingTable = _fakers.Table.Generate(); + Table existingTable = _fakers.Table.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -232,7 +232,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_relationship() { // Arrange - Table existingTable = _fakers.Table.Generate(); + Table existingTable = _fakers.Table.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -258,7 +258,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_to_ToMany_relationship() { // Arrange - Table existingTable = _fakers.Table.Generate(); + Table existingTable = _fakers.Table.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -284,7 +284,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_ToMany_relationship() { // Arrange - Table existingTable = _fakers.Table.Generate(); + Table existingTable = _fakers.Table.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Serialization/ETagTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Serialization/ETagTests.cs index 4c950ee98e..1b866d8c48 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Serialization/ETagTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Serialization/ETagTests.cs @@ -24,7 +24,7 @@ public ETagTests(IntegrationTestContext, public async Task Returns_ETag_for_HEAD_request() { // Arrange - List meetings = _fakers.Meeting.Generate(2); + List meetings = _fakers.Meeting.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -41,9 +41,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - httpResponse.Headers.ETag.ShouldNotBeNull(); + httpResponse.Headers.ETag.Should().NotBeNull(); httpResponse.Headers.ETag.IsWeak.Should().BeFalse(); - httpResponse.Headers.ETag.Tag.ShouldNotBeNullOrEmpty(); + httpResponse.Headers.ETag.Tag.Should().NotBeNullOrEmpty(); responseDocument.Should().BeEmpty(); } @@ -52,7 +52,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Returns_ETag_for_GET_request() { // Arrange - List meetings = _fakers.Meeting.Generate(2); + List meetings = _fakers.Meeting.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -69,11 +69,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - httpResponse.Headers.ETag.ShouldNotBeNull(); + httpResponse.Headers.ETag.Should().NotBeNull(); httpResponse.Headers.ETag.IsWeak.Should().BeFalse(); - httpResponse.Headers.ETag.Tag.ShouldNotBeNullOrEmpty(); + httpResponse.Headers.ETag.Tag.Should().NotBeNullOrEmpty(); - responseDocument.ShouldNotBeEmpty(); + responseDocument.Should().NotBeEmpty(); } [Fact] @@ -90,7 +90,7 @@ public async Task Returns_no_ETag_for_failed_GET_request() httpResponse.Headers.ETag.Should().BeNull(); - responseDocument.ShouldNotBeEmpty(); + responseDocument.Should().NotBeEmpty(); } [Fact] @@ -98,7 +98,7 @@ public async Task Returns_no_ETag_for_POST_request() { // Arrange var newId = Guid.NewGuid(); - string newTitle = _fakers.Meeting.Generate().Title; + string newTitle = _fakers.Meeting.GenerateOne().Title; var requestBody = new { @@ -123,16 +123,16 @@ public async Task Returns_no_ETag_for_POST_request() httpResponse.Headers.ETag.Should().BeNull(); - responseDocument.ShouldNotBeEmpty(); + responseDocument.Should().NotBeEmpty(); } [Fact] public async Task Fails_on_ETag_in_PATCH_request() { // Arrange - Meeting existingMeeting = _fakers.Meeting.Generate(); + Meeting existingMeeting = _fakers.Meeting.GenerateOne(); - string newTitle = _fakers.Meeting.Generate().Title; + string newTitle = _fakers.Meeting.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -158,19 +158,18 @@ await _testContext.RunOnDatabaseAsync(async dbContext => Action setRequestHeaders = headers => headers.IfMatch.ParseAdd("\"12345\""); // Act - (HttpResponseMessage httpResponse, Document responseDocument) = - await _testContext.ExecutePatchAsync(route, requestBody, setRequestHeaders: setRequestHeaders); + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePatchAsync(route, requestBody, setRequestHeaders); // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.PreconditionFailed); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.PreconditionFailed); error.Title.Should().Be("Detection of mid-air edit collisions using ETags is not supported."); error.Detail.Should().BeNull(); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Header.Should().Be("If-Match"); } @@ -178,7 +177,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Returns_NotModified_for_matching_ETag() { // Arrange - List meetings = _fakers.Meeting.Generate(2); + List meetings = _fakers.Meeting.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -201,9 +200,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse2.ShouldHaveStatusCode(HttpStatusCode.NotModified); - httpResponse2.Headers.ETag.ShouldNotBeNull(); + httpResponse2.Headers.ETag.Should().NotBeNull(); httpResponse2.Headers.ETag.IsWeak.Should().BeFalse(); - httpResponse2.Headers.ETag.Tag.ShouldNotBeNullOrEmpty(); + httpResponse2.Headers.ETag.Tag.Should().NotBeNullOrEmpty(); responseDocument2.Should().BeEmpty(); } @@ -212,7 +211,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Returns_content_for_mismatching_ETag() { // Arrange - List meetings = _fakers.Meeting.Generate(2); + List meetings = _fakers.Meeting.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -231,10 +230,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - httpResponse.Headers.ETag.ShouldNotBeNull(); + httpResponse.Headers.ETag.Should().NotBeNull(); httpResponse.Headers.ETag.IsWeak.Should().BeFalse(); - httpResponse.Headers.ETag.Tag.ShouldNotBeNullOrEmpty(); + httpResponse.Headers.ETag.Tag.Should().NotBeNullOrEmpty(); - responseDocument.ShouldNotBeEmpty(); + responseDocument.Should().NotBeEmpty(); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Serialization/SerializationDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Serialization/SerializationDbContext.cs index c90e22f736..713ea20545 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Serialization/SerializationDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Serialization/SerializationDbContext.cs @@ -7,7 +7,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.Serialization; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class SerializationDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class SerializationDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet Meetings => Set(); public DbSet Attendees => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Serialization/SerializationTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Serialization/SerializationTests.cs index fdac2bfc64..e500ebcdf9 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Serialization/SerializationTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Serialization/SerializationTests.cs @@ -42,7 +42,7 @@ public SerializationTests(IntegrationTestContext { @@ -84,8 +84,8 @@ public async Task Returns_no_body_for_failed_HEAD_request() public async Task Can_get_primary_resources_with_include() { // Arrange - Meeting meeting = _fakers.Meeting.Generate(); - meeting.Attendees = _fakers.MeetingAttendee.Generate(1); + Meeting meeting = _fakers.Meeting.GenerateOne(); + meeting.Attendees = _fakers.MeetingAttendee.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -178,7 +178,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resource_with_empty_ToOne_include() { // Arrange - MeetingAttendee attendee = _fakers.MeetingAttendee.Generate(); + MeetingAttendee attendee = _fakers.MeetingAttendee.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -233,7 +233,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resources_with_empty_ToMany_include() { // Arrange - Meeting meeting = _fakers.Meeting.Generate(); + Meeting meeting = _fakers.Meeting.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -296,7 +296,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resource_by_ID() { // Arrange - Meeting meeting = _fakers.Meeting.Generate(); + Meeting meeting = _fakers.Meeting.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -382,8 +382,8 @@ public async Task Cannot_get_unknown_primary_resource_by_ID() public async Task Can_get_secondary_resource() { // Arrange - MeetingAttendee attendee = _fakers.MeetingAttendee.Generate(); - attendee.Meeting = _fakers.Meeting.Generate(); + MeetingAttendee attendee = _fakers.MeetingAttendee.GenerateOne(); + attendee.Meeting = _fakers.Meeting.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -436,7 +436,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_unknown_secondary_resource() { // Arrange - MeetingAttendee attendee = _fakers.MeetingAttendee.Generate(); + MeetingAttendee attendee = _fakers.MeetingAttendee.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -466,8 +466,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_secondary_resources() { // Arrange - Meeting meeting = _fakers.Meeting.Generate(); - meeting.Attendees = _fakers.MeetingAttendee.Generate(1); + Meeting meeting = _fakers.Meeting.GenerateOne(); + meeting.Attendees = _fakers.MeetingAttendee.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -527,7 +527,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_unknown_secondary_resources() { // Arrange - Meeting meeting = _fakers.Meeting.Generate(); + Meeting meeting = _fakers.Meeting.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -561,8 +561,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_ToOne_relationship() { // Arrange - MeetingAttendee attendee = _fakers.MeetingAttendee.Generate(); - attendee.Meeting = _fakers.Meeting.Generate(); + MeetingAttendee attendee = _fakers.MeetingAttendee.GenerateOne(); + attendee.Meeting = _fakers.Meeting.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -596,8 +596,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_ToMany_relationship() { // Arrange - Meeting meeting = _fakers.Meeting.Generate(); - meeting.Attendees = _fakers.MeetingAttendee.Generate(2); + Meeting meeting = _fakers.Meeting.GenerateOne(); + meeting.Attendees = _fakers.MeetingAttendee.GenerateList(2); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -644,7 +644,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_resource_with_side_effects() { // Arrange - Meeting newMeeting = _fakers.Meeting.Generate(); + Meeting newMeeting = _fakers.Meeting.GenerateOne(); newMeeting.Id = Guid.NewGuid(); var requestBody = new @@ -712,7 +712,7 @@ public async Task Can_create_resource_with_side_effects() public async Task Can_update_resource_with_side_effects() { // Arrange - MeetingAttendee existingAttendee = _fakers.MeetingAttendee.Generate(); + MeetingAttendee existingAttendee = _fakers.MeetingAttendee.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -778,8 +778,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_relationship_for_type_at_end() { // Arrange - MeetingAttendee existingAttendee = _fakers.MeetingAttendee.Generate(); - existingAttendee.Meeting = _fakers.Meeting.Generate(); + MeetingAttendee existingAttendee = _fakers.MeetingAttendee.GenerateOne(); + existingAttendee.Meeting = _fakers.Meeting.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -827,7 +827,7 @@ public async Task Includes_version_at_resource_endpoint() var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); options.IncludeJsonApiVersion = true; - MeetingAttendee attendee = _fakers.MeetingAttendee.Generate(); + MeetingAttendee attendee = _fakers.MeetingAttendee.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionAwareResourceService.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionAwareResourceService.cs index 8f1ce719e8..ce64b677ee 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionAwareResourceService.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionAwareResourceService.cs @@ -7,20 +7,19 @@ using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Services; using Microsoft.Extensions.Logging; -using TestBuildingBlocks; namespace JsonApiDotNetCoreTests.IntegrationTests.SoftDeletion; [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] public class SoftDeletionAwareResourceService( - ISystemClock systemClock, ITargetedFields targetedFields, IResourceRepositoryAccessor repositoryAccessor, IQueryLayerComposer queryLayerComposer, + TimeProvider timeProvider, ITargetedFields targetedFields, IResourceRepositoryAccessor repositoryAccessor, IQueryLayerComposer queryLayerComposer, IPaginationContext paginationContext, IJsonApiOptions options, ILoggerFactory loggerFactory, IJsonApiRequest request, IResourceChangeTracker resourceChangeTracker, IResourceDefinitionAccessor resourceDefinitionAccessor) : JsonApiResourceService(repositoryAccessor, queryLayerComposer, paginationContext, options, loggerFactory, request, resourceChangeTracker, resourceDefinitionAccessor) where TResource : class, IIdentifiable { - private readonly ISystemClock _systemClock = systemClock; + private readonly TimeProvider _timeProvider = timeProvider; private readonly ITargetedFields _targetedFields = targetedFields; private readonly IResourceRepositoryAccessor _repositoryAccessor = repositoryAccessor; private readonly IJsonApiRequest _request = request; @@ -90,7 +89,7 @@ private async Task SoftDeleteAsync([DisallowNull] TId id, CancellationToken canc { TResource resourceFromDatabase = await GetPrimaryResourceForUpdateAsync(id, cancellationToken); - ((ISoftDeletable)resourceFromDatabase).SoftDeletedAt = _systemClock.UtcNow; + ((ISoftDeletable)resourceFromDatabase).SoftDeletedAt = _timeProvider.GetUtcNow(); // A delete operation does not target any fields, so we can just pass resourceFromDatabase twice. await _repositoryAccessor.UpdateAsync(resourceFromDatabase, resourceFromDatabase, cancellationToken); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionDbContext.cs index 98da66fc3d..0efa423df5 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionDbContext.cs @@ -7,7 +7,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.SoftDeletion; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class SoftDeletionDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class SoftDeletionDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet Companies => Set(); public DbSet Departments => Set(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionFakers.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionFakers.cs index 1cbf435c45..aa25cae9d2 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionFakers.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionFakers.cs @@ -8,14 +8,23 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.SoftDeletion; internal sealed class SoftDeletionFakers { - private readonly Lazy> _lazyCompanyFaker = new(() => new Faker() - .MakeDeterministic() - .RuleFor(company => company.Name, faker => faker.Company.CompanyName())); + private readonly Lazy> _lazyCompanyFaker; - private readonly Lazy> _lazyDepartmentFaker = new(() => new Faker() - .MakeDeterministic() - .RuleFor(department => department.Name, faker => faker.Commerce.Department())); + private readonly Lazy> _lazyDepartmentFaker; public Faker Company => _lazyCompanyFaker.Value; public Faker Department => _lazyDepartmentFaker.Value; + + public SoftDeletionFakers(DateTimeOffset systemTime) + { + DateTime systemTimeUtc = systemTime.UtcDateTime; + + _lazyCompanyFaker = new Lazy>(() => new Faker() + .MakeDeterministic(systemTimeUtc) + .RuleFor(company => company.Name, faker => faker.Company.CompanyName())); + + _lazyDepartmentFaker = new Lazy>(() => new Faker() + .MakeDeterministic(systemTimeUtc) + .RuleFor(department => department.Name, faker => faker.Commerce.Department())); + } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionTests.cs index 7bd7fe66f1..2badb7e252 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/SoftDeletion/SoftDeletionTests.cs @@ -5,6 +5,7 @@ using JsonApiDotNetCore.Serialization.Objects; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using TestBuildingBlocks; using Xunit; @@ -12,10 +13,11 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.SoftDeletion; public sealed class SoftDeletionTests : IClassFixture, SoftDeletionDbContext>> { + private static readonly DateTimeOffset CurrentTime = 1.January(2005).AsUtc(); private static readonly DateTimeOffset SoftDeletionTime = 1.January(2001).AsUtc(); private readonly IntegrationTestContext, SoftDeletionDbContext> _testContext; - private readonly SoftDeletionFakers _fakers = new(); + private readonly SoftDeletionFakers _fakers = new(CurrentTime); public SoftDeletionTests(IntegrationTestContext, SoftDeletionDbContext> testContext) { @@ -28,19 +30,19 @@ public SoftDeletionTests(IntegrationTestContext>(); services.AddResourceService>(); - - services.AddSingleton(new FrozenSystemClock - { - UtcNow = 1.January(2005).AsUtc() - }); }); + + testContext.PostConfigureServices(services => services.Replace(ServiceDescriptor.Singleton(new FrozenTimeProvider(CurrentTime)))); + + var timeProvider = (FrozenTimeProvider)testContext.Factory.Services.GetRequiredService(); + timeProvider.Reset(); } [Fact] public async Task Get_primary_resources_excludes_soft_deleted() { // Arrange - List departments = _fakers.Department.Generate(2); + List departments = _fakers.Department.GenerateList(2); departments[0].SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -58,7 +60,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(departments[1].StringId); } @@ -66,7 +68,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Filter_on_primary_resources_excludes_soft_deleted() { // Arrange - List departments = _fakers.Department.Generate(3); + List departments = _fakers.Department.GenerateList(3); departments[0].Name = "Support"; @@ -90,7 +92,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(departments[0].StringId); } @@ -98,12 +100,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_primary_resources_with_include_excludes_soft_deleted() { // Arrange - List companies = _fakers.Company.Generate(2); + List companies = _fakers.Company.GenerateList(2); companies[0].SoftDeletedAt = SoftDeletionTime; - companies[0].Departments = _fakers.Department.Generate(1); + companies[0].Departments = _fakers.Department.GenerateList(1); - companies[1].Departments = _fakers.Department.Generate(2); + companies[1].Departments = _fakers.Department.GenerateList(2); companies[1].Departments.ElementAt(1).SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -121,11 +123,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Type.Should().Be("companies"); responseDocument.Data.ManyValue[0].Id.Should().Be(companies[1].StringId); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Type.Should().Be("departments"); responseDocument.Included[0].Id.Should().Be(companies[1].Departments.ElementAt(0).StringId); } @@ -134,7 +136,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_soft_deleted_primary_resource_by_ID() { // Arrange - Department department = _fakers.Department.Generate(); + Department department = _fakers.Department.GenerateOne(); department.SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -151,7 +153,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -163,9 +165,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resources_for_soft_deleted_parent() { // Arrange - Company company = _fakers.Company.Generate(); + Company company = _fakers.Company.GenerateOne(); company.SoftDeletedAt = SoftDeletionTime; - company.Departments = _fakers.Department.Generate(1); + company.Departments = _fakers.Department.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -181,7 +183,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -193,8 +195,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_secondary_resources_excludes_soft_deleted() { // Arrange - Company company = _fakers.Company.Generate(); - company.Departments = _fakers.Department.Generate(2); + Company company = _fakers.Company.GenerateOne(); + company.Departments = _fakers.Department.GenerateList(2); company.Departments.ElementAt(0).SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -211,7 +213,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(company.Departments.ElementAt(1).StringId); } @@ -219,9 +221,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_secondary_resource_for_soft_deleted_parent() { // Arrange - Department department = _fakers.Department.Generate(); + Department department = _fakers.Department.GenerateOne(); department.SoftDeletedAt = SoftDeletionTime; - department.Company = _fakers.Company.Generate(); + department.Company = _fakers.Company.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -237,7 +239,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -249,8 +251,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_soft_deleted_secondary_resource() { // Arrange - Department department = _fakers.Department.Generate(); - department.Company = _fakers.Company.Generate(); + Department department = _fakers.Department.GenerateOne(); + department.Company = _fakers.Company.GenerateOne(); department.Company.SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -274,9 +276,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_ToMany_relationship_for_soft_deleted_parent() { // Arrange - Company company = _fakers.Company.Generate(); + Company company = _fakers.Company.GenerateOne(); company.SoftDeletedAt = SoftDeletionTime; - company.Departments = _fakers.Department.Generate(1); + company.Departments = _fakers.Department.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -292,7 +294,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -304,8 +306,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_ToMany_relationship_excludes_soft_deleted() { // Arrange - Company company = _fakers.Company.Generate(); - company.Departments = _fakers.Department.Generate(2); + Company company = _fakers.Company.GenerateOne(); + company.Departments = _fakers.Department.GenerateList(2); company.Departments.ElementAt(0).SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -322,7 +324,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be(company.Departments.ElementAt(1).StringId); } @@ -330,9 +332,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_get_ToOne_relationship_for_soft_deleted_parent() { // Arrange - Department department = _fakers.Department.Generate(); + Department department = _fakers.Department.GenerateOne(); department.SoftDeletedAt = SoftDeletionTime; - department.Company = _fakers.Company.Generate(); + department.Company = _fakers.Company.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -348,7 +350,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -360,8 +362,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Get_ToOne_relationship_excludes_soft_deleted() { // Arrange - Department department = _fakers.Department.Generate(); - department.Company = _fakers.Company.Generate(); + Department department = _fakers.Department.GenerateOne(); + department.Company = _fakers.Company.GenerateOne(); department.Company.SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -385,10 +387,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_resource_with_ToMany_relationship_to_soft_deleted() { // Arrange - Department existingDepartment = _fakers.Department.Generate(); + Department existingDepartment = _fakers.Department.GenerateOne(); existingDepartment.SoftDeletedAt = SoftDeletionTime; - string newCompanyName = _fakers.Company.Generate().Name; + string newCompanyName = _fakers.Company.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -430,7 +432,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -444,10 +446,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_create_resource_with_ToOne_relationship_to_soft_deleted() { // Arrange - Company existingCompany = _fakers.Company.Generate(); + Company existingCompany = _fakers.Company.GenerateOne(); existingCompany.SoftDeletedAt = SoftDeletionTime; - string newDepartmentName = _fakers.Department.Generate().Name; + string newDepartmentName = _fakers.Department.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -486,7 +488,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -498,10 +500,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_soft_deleted_resource() { // Arrange - Company existingCompany = _fakers.Company.Generate(); + Company existingCompany = _fakers.Company.GenerateOne(); existingCompany.SoftDeletedAt = SoftDeletionTime; - string newCompanyName = _fakers.Company.Generate().Name; + string newCompanyName = _fakers.Company.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -530,7 +532,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -542,9 +544,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_ToMany_relationship_to_soft_deleted() { // Arrange - Company existingCompany = _fakers.Company.Generate(); + Company existingCompany = _fakers.Company.GenerateOne(); - Department existingDepartment = _fakers.Department.Generate(); + Department existingDepartment = _fakers.Department.GenerateOne(); existingDepartment.SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -584,7 +586,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -598,9 +600,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_resource_with_ToOne_relationship_to_soft_deleted() { // Arrange - Department existingDepartment = _fakers.Department.Generate(); + Department existingDepartment = _fakers.Department.GenerateOne(); - Company existingCompany = _fakers.Company.Generate(); + Company existingCompany = _fakers.Company.GenerateOne(); existingCompany.SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -637,7 +639,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -649,9 +651,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_ToMany_relationship_for_soft_deleted_parent() { // Arrange - Company existingCompany = _fakers.Company.Generate(); + Company existingCompany = _fakers.Company.GenerateOne(); existingCompany.SoftDeletedAt = SoftDeletionTime; - existingCompany.Departments = _fakers.Department.Generate(1); + existingCompany.Departments = _fakers.Department.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -672,7 +674,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -684,9 +686,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_ToMany_relationship_to_soft_deleted() { // Arrange - Company existingCompany = _fakers.Company.Generate(); + Company existingCompany = _fakers.Company.GenerateOne(); - Department existingDepartment = _fakers.Department.Generate(); + Department existingDepartment = _fakers.Department.GenerateOne(); existingDepartment.SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -715,7 +717,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -729,7 +731,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_ToOne_relationship_for_soft_deleted_parent() { // Arrange - Department existingDepartment = _fakers.Department.Generate(); + Department existingDepartment = _fakers.Department.GenerateOne(); existingDepartment.SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -751,7 +753,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -763,9 +765,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_update_ToOne_relationship_to_soft_deleted() { // Arrange - Department existingDepartment = _fakers.Department.Generate(); + Department existingDepartment = _fakers.Department.GenerateOne(); - Company existingCompany = _fakers.Company.Generate(); + Company existingCompany = _fakers.Company.GenerateOne(); existingCompany.SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -791,7 +793,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -803,10 +805,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_to_ToMany_relationship_for_soft_deleted_parent() { // Arrange - Company existingCompany = _fakers.Company.Generate(); + Company existingCompany = _fakers.Company.GenerateOne(); existingCompany.SoftDeletedAt = SoftDeletionTime; - Department existingDepartment = _fakers.Department.Generate(); + Department existingDepartment = _fakers.Department.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -834,7 +836,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -846,9 +848,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_add_to_ToMany_relationship_with_soft_deleted() { // Arrange - Company existingCompany = _fakers.Company.Generate(); + Company existingCompany = _fakers.Company.GenerateOne(); - Department existingDepartment = _fakers.Department.Generate(); + Department existingDepartment = _fakers.Department.GenerateOne(); existingDepartment.SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -877,7 +879,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -891,9 +893,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_from_ToMany_relationship_for_soft_deleted_parent() { // Arrange - Company existingCompany = _fakers.Company.Generate(); + Company existingCompany = _fakers.Company.GenerateOne(); existingCompany.SoftDeletedAt = SoftDeletionTime; - existingCompany.Departments = _fakers.Department.Generate(1); + existingCompany.Departments = _fakers.Department.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -921,7 +923,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -933,8 +935,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_remove_from_ToMany_relationship_with_soft_deleted() { // Arrange - Company existingCompany = _fakers.Company.Generate(); - existingCompany.Departments = _fakers.Department.Generate(1); + Company existingCompany = _fakers.Company.GenerateOne(); + existingCompany.Departments = _fakers.Department.GenerateList(1); existingCompany.Departments.ElementAt(0).SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -963,7 +965,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -977,7 +979,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_soft_delete_resource() { // Arrange - Company existingCompany = _fakers.Company.Generate(); + Company existingCompany = _fakers.Company.GenerateOne(); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -1000,7 +1002,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => Company companyInDatabase = await dbContext.Companies.IgnoreQueryFilters().FirstWithIdAsync(existingCompany.Id); companyInDatabase.Name.Should().Be(existingCompany.Name); - companyInDatabase.SoftDeletedAt.ShouldNotBeNull(); + companyInDatabase.SoftDeletedAt.Should().NotBeNull(); }); } @@ -1008,7 +1010,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Cannot_delete_soft_deleted_resource() { // Arrange - Department existingDepartment = _fakers.Department.Generate(); + Department existingDepartment = _fakers.Department.GenerateOne(); existingDepartment.SoftDeletedAt = SoftDeletionTime; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -1025,7 +1027,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/EmptyGuidAsKeyTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/EmptyGuidAsKeyTests.cs index 93881be9eb..e836c049bf 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/EmptyGuidAsKeyTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/EmptyGuidAsKeyTests.cs @@ -30,7 +30,7 @@ public EmptyGuidAsKeyTests(IntegrationTestContext maps = _fakers.Map.Generate(2); + List maps = _fakers.Map.GenerateList(2); maps[0].Id = Guid.Empty; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -48,12 +48,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be("00000000-0000-0000-0000-000000000000"); responseDocument.Data.ManyValue[0].With(resource => { - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be("/maps/00000000-0000-0000-0000-000000000000"); }); } @@ -62,9 +62,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resource_by_empty_ID_with_include() { // Arrange - Map map = _fakers.Map.Generate(); + Map map = _fakers.Map.GenerateOne(); map.Id = Guid.Empty; - map.Game = _fakers.Game.Generate(); + map.Game = _fakers.Game.GenerateOne(); map.Game.Id = 0; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -82,12 +82,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be("00000000-0000-0000-0000-000000000000"); - responseDocument.Data.SingleValue.Links.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Links.Should().NotBeNull(); responseDocument.Data.SingleValue.Links.Self.Should().Be("/maps/00000000-0000-0000-0000-000000000000"); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Id.Should().Be("0"); } @@ -95,7 +95,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_resource_with_empty_ID() { // Arrange - string newName = _fakers.Map.Generate().Name; + string newName = _fakers.Map.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -131,7 +131,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Map mapInDatabase = await dbContext.Maps.FirstWithIdAsync((Guid?)Guid.Empty); - mapInDatabase.ShouldNotBeNull(); + mapInDatabase.Should().NotBeNull(); mapInDatabase.Name.Should().Be(newName); }); } @@ -140,10 +140,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_empty_ID() { // Arrange - Map existingMap = _fakers.Map.Generate(); + Map existingMap = _fakers.Map.GenerateOne(); existingMap.Id = Guid.Empty; - string newName = _fakers.Map.Generate().Name; + string newName = _fakers.Map.GenerateOne().Name; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -179,7 +179,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Map mapInDatabase = await dbContext.Maps.FirstWithIdAsync((Guid?)Guid.Empty); - mapInDatabase.ShouldNotBeNull(); + mapInDatabase.Should().NotBeNull(); mapInDatabase.Name.Should().Be(newName); }); } @@ -188,8 +188,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_ToOne_relationship_with_empty_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); - existingGame.ActiveMap = _fakers.Map.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.ActiveMap = _fakers.Map.GenerateOne(); existingGame.ActiveMap.Id = Guid.Empty; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -218,7 +218,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Game gameInDatabase = await dbContext.Games.Include(game => game.ActiveMap).FirstWithIdAsync(existingGame.Id); - gameInDatabase.ShouldNotBeNull(); + gameInDatabase.Should().NotBeNull(); gameInDatabase.ActiveMap.Should().BeNull(); }); } @@ -227,9 +227,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_assign_ToOne_relationship_with_empty_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); - Map existingMap = _fakers.Map.Generate(); + Map existingMap = _fakers.Map.GenerateOne(); existingMap.Id = Guid.Empty; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -262,8 +262,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Game gameInDatabase = await dbContext.Games.Include(game => game.ActiveMap).FirstWithIdAsync(existingGame.Id); - gameInDatabase.ShouldNotBeNull(); - gameInDatabase.ActiveMap.ShouldNotBeNull(); + gameInDatabase.Should().NotBeNull(); + gameInDatabase.ActiveMap.Should().NotBeNull(); gameInDatabase.ActiveMap.Id.Should().Be(Guid.Empty); }); } @@ -272,10 +272,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ToOne_relationship_with_empty_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); - existingGame.ActiveMap = _fakers.Map.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.ActiveMap = _fakers.Map.GenerateOne(); - Map existingMap = _fakers.Map.Generate(); + Map existingMap = _fakers.Map.GenerateOne(); existingMap.Id = Guid.Empty; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -308,8 +308,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Game gameInDatabase = await dbContext.Games.Include(game => game.ActiveMap).FirstWithIdAsync(existingGame.Id); - gameInDatabase.ShouldNotBeNull(); - gameInDatabase.ActiveMap.ShouldNotBeNull(); + gameInDatabase.Should().NotBeNull(); + gameInDatabase.ActiveMap.Should().NotBeNull(); gameInDatabase.ActiveMap.Id.Should().Be(Guid.Empty); }); } @@ -318,8 +318,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_ToMany_relationship_with_empty_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); - existingGame.Maps = _fakers.Map.Generate(2); + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.Maps = _fakers.Map.GenerateList(2); existingGame.Maps.ElementAt(0).Id = Guid.Empty; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -348,7 +348,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Game gameInDatabase = await dbContext.Games.Include(game => game.Maps).FirstWithIdAsync(existingGame.Id); - gameInDatabase.ShouldNotBeNull(); + gameInDatabase.Should().NotBeNull(); gameInDatabase.Maps.Should().BeEmpty(); }); } @@ -357,9 +357,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_assign_ToMany_relationship_with_empty_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); - Map existingMap = _fakers.Map.Generate(); + Map existingMap = _fakers.Map.GenerateOne(); existingMap.Id = Guid.Empty; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -395,8 +395,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Game gameInDatabase = await dbContext.Games.Include(game => game.Maps).FirstWithIdAsync(existingGame.Id); - gameInDatabase.ShouldNotBeNull(); - gameInDatabase.Maps.ShouldHaveCount(1); + gameInDatabase.Should().NotBeNull(); + gameInDatabase.Maps.Should().HaveCount(1); gameInDatabase.Maps.ElementAt(0).Id.Should().Be(Guid.Empty); }); } @@ -405,10 +405,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ToMany_relationship_with_empty_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); - existingGame.Maps = _fakers.Map.Generate(2); + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.Maps = _fakers.Map.GenerateList(2); - Map existingMap = _fakers.Map.Generate(); + Map existingMap = _fakers.Map.GenerateOne(); existingMap.Id = Guid.Empty; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -444,8 +444,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Game gameInDatabase = await dbContext.Games.Include(game => game.Maps).FirstWithIdAsync(existingGame.Id); - gameInDatabase.ShouldNotBeNull(); - gameInDatabase.Maps.ShouldHaveCount(1); + gameInDatabase.Should().NotBeNull(); + gameInDatabase.Maps.Should().HaveCount(1); gameInDatabase.Maps.ElementAt(0).Id.Should().Be(Guid.Empty); }); } @@ -454,10 +454,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_to_ToMany_relationship_with_empty_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); - existingGame.Maps = _fakers.Map.Generate(1); + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.Maps = _fakers.Map.GenerateList(1); - Map existingMap = _fakers.Map.Generate(); + Map existingMap = _fakers.Map.GenerateOne(); existingMap.Id = Guid.Empty; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -493,8 +493,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Game gameInDatabase = await dbContext.Games.Include(game => game.Maps).FirstWithIdAsync(existingGame.Id); - gameInDatabase.ShouldNotBeNull(); - gameInDatabase.Maps.ShouldHaveCount(2); + gameInDatabase.Should().NotBeNull(); + gameInDatabase.Maps.Should().HaveCount(2); gameInDatabase.Maps.Should().ContainSingle(map => map.Id == Guid.Empty); }); } @@ -503,8 +503,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_ToMany_relationship_with_empty_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); - existingGame.Maps = _fakers.Map.Generate(2); + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.Maps = _fakers.Map.GenerateList(2); existingGame.Maps.ElementAt(0).Id = Guid.Empty; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -540,8 +540,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Game gameInDatabase = await dbContext.Games.Include(game => game.Maps).FirstWithIdAsync(existingGame.Id); - gameInDatabase.ShouldNotBeNull(); - gameInDatabase.Maps.ShouldHaveCount(1); + gameInDatabase.Should().NotBeNull(); + gameInDatabase.Maps.Should().HaveCount(1); gameInDatabase.Maps.Should().ContainSingle(map => map.Id != Guid.Empty); }); } @@ -550,7 +550,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource_with_empty_ID() { // Arrange - Map existingMap = _fakers.Map.Generate(); + Map existingMap = _fakers.Map.GenerateOne(); existingMap.Id = Guid.Empty; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -572,9 +572,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => await _testContext.RunOnDatabaseAsync(async dbContext => { - Map? gameInDatabase = await dbContext.Maps.FirstWithIdOrDefaultAsync(existingMap.Id); + Map? mapInDatabase = await dbContext.Maps.FirstWithIdOrDefaultAsync(existingMap.Id); - gameInDatabase.Should().BeNull(); + mapInDatabase.Should().BeNull(); }); } } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/Game.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/Game.cs index 172ab35a2a..55372d4b0f 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/Game.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/Game.cs @@ -17,6 +17,9 @@ public sealed class Game : Identifiable [Attr] public Guid SessionToken => Guid.NewGuid(); + [HasOne] + public Player? Host { get; set; } + [HasMany] public ICollection ActivePlayers { get; set; } = new List(); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/Player.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/Player.cs index cc38d5360b..52f52d112c 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/Player.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/Player.cs @@ -1,12 +1,13 @@ using JetBrains.Annotations; +using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; namespace JsonApiDotNetCoreTests.IntegrationTests.ZeroKeys; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -[Resource(ControllerNamespace = "JsonApiDotNetCoreTests.IntegrationTests.ZeroKeys")] -public sealed class Player : Identifiable +[Resource(ControllerNamespace = "JsonApiDotNetCoreTests.IntegrationTests.ZeroKeys", ClientIdGeneration = ClientIdGenerationMode.Allowed)] +public sealed class Player : Identifiable { [Attr] public string EmailAddress { get; set; } = null!; diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/WhiteSpaceAsKeyTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/WhiteSpaceAsKeyTests.cs new file mode 100644 index 0000000000..2ed32314e0 --- /dev/null +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/WhiteSpaceAsKeyTests.cs @@ -0,0 +1,655 @@ +using System.Net; +using System.Reflection; +using FluentAssertions; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Serialization.Objects; +using Microsoft.AspNetCore.Mvc.ModelBinding; +using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using TestBuildingBlocks; +using Xunit; + +namespace JsonApiDotNetCoreTests.IntegrationTests.ZeroKeys; + +public sealed class WhiteSpaceAsKeyTests : IClassFixture, ZeroKeyDbContext>> +{ + // An empty string id makes no sense: get-by-id, update and delete resource are impossible, and rendered links are unusable. + private const string SingleSpace = " "; + + private readonly IntegrationTestContext, ZeroKeyDbContext> _testContext; + private readonly ZeroKeyFakers _fakers = new(); + + public WhiteSpaceAsKeyTests(IntegrationTestContext, ZeroKeyDbContext> testContext) + { + _testContext = testContext; + + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + + testContext.PostConfigureServices(services => + { + ServiceDescriptor serviceDescriptor = services.Single(descriptor => descriptor.ServiceType == typeof(IModelMetadataProvider)); + services.Remove(serviceDescriptor); + Type existingProviderType = serviceDescriptor.ImplementationType!; + + services.AddSingleton(serviceProvider => + { + var existingProvider = (ModelMetadataProvider)ActivatorUtilities.CreateInstance(serviceProvider, existingProviderType); + return new PreserveWhitespaceModelMetadataProvider(existingProvider); + }); + }); + + var options = (JsonApiOptions)testContext.Factory.Services.GetRequiredService(); + options.UseRelativeLinks = true; + } + + [Fact] + public async Task Can_filter_by_space_ID_on_primary_resources() + { + // Arrange + List players = _fakers.Player.GenerateList(2); + players[0].Id = SingleSpace; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Players.AddRange(players); + await dbContext.SaveChangesAsync(); + }); + + const string route = "/players?filter=equals(id,' ')"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecuteGetAsync(route); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); + + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Id.Should().Be(SingleSpace); + + responseDocument.Data.ManyValue[0].With(resource => + { + resource.Links.Should().NotBeNull(); + resource.Links.Self.Should().Be("/players/%20"); + }); + } + + [Fact] + public async Task Can_get_primary_resource_by_space_ID_with_include() + { + // Arrange + Player player = _fakers.Player.GenerateOne(); + player.Id = SingleSpace; + player.ActiveGame = _fakers.Game.GenerateOne(); + player.ActiveGame.Id = 0; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTablesAsync(); + dbContext.Players.Add(player); + await dbContext.SaveChangesAsync(); + }); + + const string route = "/players/%20?include=activeGame"; + + // Act + (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecuteGetAsync(route); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); + + responseDocument.Data.SingleValue.Should().NotBeNull(); + responseDocument.Data.SingleValue.Id.Should().Be(SingleSpace); + responseDocument.Data.SingleValue.Links.Should().NotBeNull(); + responseDocument.Data.SingleValue.Links.Self.Should().Be("/players/%20"); + + responseDocument.Included.Should().HaveCount(1); + responseDocument.Included[0].Id.Should().Be("0"); + } + + [Fact] + public async Task Can_create_resource_with_space_ID() + { + // Arrange + string newEmailAddress = _fakers.Player.GenerateOne().EmailAddress; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + }); + + var requestBody = new + { + data = new + { + type = "players", + id = SingleSpace, + attributes = new + { + emailAddress = newEmailAddress + } + } + }; + + const string route = "/players"; + + // Act + (HttpResponseMessage httpResponse, string responseDocument) = await _testContext.ExecutePostAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NoContent); + + httpResponse.Headers.Location.Should().Be("/players/%20"); + + responseDocument.Should().BeEmpty(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Player playerInDatabase = await dbContext.Players.FirstWithIdAsync((string?)SingleSpace); + + playerInDatabase.Should().NotBeNull(); + playerInDatabase.EmailAddress.Should().Be(newEmailAddress); + }); + } + + [Fact] + public async Task Can_update_resource_with_space_ID() + { + // Arrange + Player existingPlayer = _fakers.Player.GenerateOne(); + existingPlayer.Id = SingleSpace; + + string newEmailAddress = _fakers.Player.GenerateOne().EmailAddress; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Players.Add(existingPlayer); + await dbContext.SaveChangesAsync(); + }); + + var requestBody = new + { + data = new + { + type = "players", + id = SingleSpace, + attributes = new + { + emailAddress = newEmailAddress + } + } + }; + + const string route = "/players/%20"; + + // Act + (HttpResponseMessage httpResponse, string responseDocument) = await _testContext.ExecutePatchAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NoContent); + + responseDocument.Should().BeEmpty(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Player playerInDatabase = await dbContext.Players.FirstWithIdAsync((string?)SingleSpace); + + playerInDatabase.Should().NotBeNull(); + playerInDatabase.EmailAddress.Should().Be(newEmailAddress); + }); + } + + [Fact] + public async Task Can_clear_ToOne_relationship_with_space_ID() + { + // Arrange + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.Host = _fakers.Player.GenerateOne(); + existingGame.Host.Id = string.Empty; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Games.Add(existingGame); + await dbContext.SaveChangesAsync(); + }); + + var requestBody = new + { + data = (object?)null + }; + + string route = $"/games/{existingGame.StringId}/relationships/host"; + + // Act + (HttpResponseMessage httpResponse, string responseDocument) = await _testContext.ExecutePatchAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NoContent); + + responseDocument.Should().BeEmpty(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Game gameInDatabase = await dbContext.Games.Include(game => game.Host).FirstWithIdAsync(existingGame.Id); + + gameInDatabase.Should().NotBeNull(); + gameInDatabase.Host.Should().BeNull(); + }); + } + + [Fact] + public async Task Can_assign_ToOne_relationship_with_space_ID() + { + // Arrange + Game existingGame = _fakers.Game.GenerateOne(); + + Player existingPlayer = _fakers.Player.GenerateOne(); + existingPlayer.Id = SingleSpace; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.AddInRange(existingGame, existingPlayer); + await dbContext.SaveChangesAsync(); + }); + + var requestBody = new + { + data = new + { + type = "players", + id = SingleSpace + } + }; + + string route = $"/games/{existingGame.StringId}/relationships/host"; + + // Act + (HttpResponseMessage httpResponse, string responseDocument) = await _testContext.ExecutePatchAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NoContent); + + responseDocument.Should().BeEmpty(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Game gameInDatabase = await dbContext.Games.Include(game => game.Host).FirstWithIdAsync(existingGame.Id); + + gameInDatabase.Should().NotBeNull(); + gameInDatabase.Host.Should().NotBeNull(); + gameInDatabase.Host.Id.Should().Be(SingleSpace); + }); + } + + [Fact] + public async Task Can_replace_ToOne_relationship_with_space_ID() + { + // Arrange + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.Host = _fakers.Player.GenerateOne(); + + Player existingPlayer = _fakers.Player.GenerateOne(); + existingPlayer.Id = SingleSpace; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.AddInRange(existingGame, existingPlayer); + await dbContext.SaveChangesAsync(); + }); + + var requestBody = new + { + data = new + { + type = "players", + id = SingleSpace + } + }; + + string route = $"/games/{existingGame.StringId}/relationships/host"; + + // Act + (HttpResponseMessage httpResponse, string responseDocument) = await _testContext.ExecutePatchAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NoContent); + + responseDocument.Should().BeEmpty(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Game gameInDatabase = await dbContext.Games.Include(game => game.Host).FirstWithIdAsync(existingGame.Id); + + gameInDatabase.Should().NotBeNull(); + gameInDatabase.Host.Should().NotBeNull(); + gameInDatabase.Host.Id.Should().Be(SingleSpace); + }); + } + + [Fact] + public async Task Can_clear_ToMany_relationship_with_space_ID() + { + // Arrange + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.ActivePlayers = _fakers.Player.GenerateList(2); + existingGame.ActivePlayers.ElementAt(0).Id = SingleSpace; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Games.Add(existingGame); + await dbContext.SaveChangesAsync(); + }); + + var requestBody = new + { + data = Array.Empty() + }; + + string route = $"/games/{existingGame.StringId}/relationships/activePlayers"; + + // Act + (HttpResponseMessage httpResponse, string responseDocument) = await _testContext.ExecutePatchAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NoContent); + + responseDocument.Should().BeEmpty(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Game gameInDatabase = await dbContext.Games.Include(game => game.ActivePlayers).FirstWithIdAsync(existingGame.Id); + + gameInDatabase.Should().NotBeNull(); + gameInDatabase.ActivePlayers.Should().BeEmpty(); + }); + } + + [Fact] + public async Task Can_assign_ToMany_relationship_with_space_ID() + { + // Arrange + Game existingGame = _fakers.Game.GenerateOne(); + + Player existingPlayer = _fakers.Player.GenerateOne(); + existingPlayer.Id = SingleSpace; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.AddInRange(existingGame, existingPlayer); + await dbContext.SaveChangesAsync(); + }); + + var requestBody = new + { + data = new[] + { + new + { + type = "players", + id = SingleSpace + } + } + }; + + string route = $"/games/{existingGame.StringId}/relationships/activePlayers"; + + // Act + (HttpResponseMessage httpResponse, string responseDocument) = await _testContext.ExecutePatchAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NoContent); + + responseDocument.Should().BeEmpty(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Game gameInDatabase = await dbContext.Games.Include(game => game.ActivePlayers).FirstWithIdAsync(existingGame.Id); + + gameInDatabase.Should().NotBeNull(); + gameInDatabase.ActivePlayers.Should().HaveCount(1); + gameInDatabase.ActivePlayers.ElementAt(0).Id.Should().Be(SingleSpace); + }); + } + + [Fact] + public async Task Can_replace_ToMany_relationship_with_space_ID() + { + // Arrange + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.ActivePlayers = _fakers.Player.GenerateList(2); + + Player existingPlayer = _fakers.Player.GenerateOne(); + existingPlayer.Id = SingleSpace; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.AddInRange(existingGame, existingPlayer); + await dbContext.SaveChangesAsync(); + }); + + var requestBody = new + { + data = new[] + { + new + { + type = "players", + id = SingleSpace + } + } + }; + + string route = $"/games/{existingGame.StringId}/relationships/activePlayers"; + + // Act + (HttpResponseMessage httpResponse, string responseDocument) = await _testContext.ExecutePatchAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NoContent); + + responseDocument.Should().BeEmpty(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Game gameInDatabase = await dbContext.Games.Include(game => game.ActivePlayers).FirstWithIdAsync(existingGame.Id); + + gameInDatabase.Should().NotBeNull(); + gameInDatabase.ActivePlayers.Should().HaveCount(1); + gameInDatabase.ActivePlayers.ElementAt(0).Id.Should().Be(SingleSpace); + }); + } + + [Fact] + public async Task Can_add_to_ToMany_relationship_with_space_ID() + { + // Arrange + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.ActivePlayers = _fakers.Player.GenerateList(1); + + Player existingPlayer = _fakers.Player.GenerateOne(); + existingPlayer.Id = SingleSpace; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.AddInRange(existingGame, existingPlayer); + await dbContext.SaveChangesAsync(); + }); + + var requestBody = new + { + data = new[] + { + new + { + type = "players", + id = SingleSpace + } + } + }; + + string route = $"/games/{existingGame.StringId}/relationships/activePlayers"; + + // Act + (HttpResponseMessage httpResponse, string responseDocument) = await _testContext.ExecutePostAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NoContent); + + responseDocument.Should().BeEmpty(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Game gameInDatabase = await dbContext.Games.Include(game => game.ActivePlayers).FirstWithIdAsync(existingGame.Id); + + gameInDatabase.Should().NotBeNull(); + gameInDatabase.ActivePlayers.Should().HaveCount(2); + gameInDatabase.ActivePlayers.Should().ContainSingle(player => player.Id == SingleSpace); + }); + } + + [Fact] + public async Task Can_remove_from_ToMany_relationship_with_space_ID() + { + // Arrange + Game existingGame = _fakers.Game.GenerateOne(); + existingGame.ActivePlayers = _fakers.Player.GenerateList(2); + existingGame.ActivePlayers.ElementAt(0).Id = SingleSpace; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Games.Add(existingGame); + await dbContext.SaveChangesAsync(); + }); + + var requestBody = new + { + data = new[] + { + new + { + type = "players", + id = SingleSpace + } + } + }; + + string route = $"/games/{existingGame.StringId}/relationships/activePlayers"; + + // Act + (HttpResponseMessage httpResponse, string responseDocument) = await _testContext.ExecuteDeleteAsync(route, requestBody); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NoContent); + + responseDocument.Should().BeEmpty(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Game gameInDatabase = await dbContext.Games.Include(game => game.ActivePlayers).FirstWithIdAsync(existingGame.Id); + + gameInDatabase.Should().NotBeNull(); + gameInDatabase.ActivePlayers.Should().HaveCount(1); + gameInDatabase.ActivePlayers.Should().ContainSingle(player => player.Id != SingleSpace); + }); + } + + [Fact] + public async Task Can_delete_resource_with_space_ID() + { + // Arrange + Player existingPlayer = _fakers.Player.GenerateOne(); + existingPlayer.Id = SingleSpace; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Players.Add(existingPlayer); + await dbContext.SaveChangesAsync(); + }); + + const string route = "/players/%20"; + + // Act + (HttpResponseMessage httpResponse, string responseDocument) = await _testContext.ExecuteDeleteAsync(route); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.NoContent); + + responseDocument.Should().BeEmpty(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Player? playerInDatabase = await dbContext.Players.FirstWithIdOrDefaultAsync((string?)existingPlayer.Id); + + playerInDatabase.Should().BeNull(); + }); + } + + private sealed class PreserveWhitespaceModelMetadataProvider : ModelMetadataProvider + { + private readonly ModelMetadataProvider _innerProvider; + + public PreserveWhitespaceModelMetadataProvider(ModelMetadataProvider innerProvider) + { + ArgumentNullException.ThrowIfNull(innerProvider); + + _innerProvider = innerProvider; + } + + public override ModelMetadata GetMetadataForType(Type modelType) + { + var metadata = (DefaultModelMetadata)_innerProvider.GetMetadataForType(modelType); + + TurnOffConvertEmptyStringToNull(metadata); + + return metadata; + } + + public override IEnumerable GetMetadataForProperties(Type modelType) + { + return _innerProvider.GetMetadataForProperties(modelType); + } + + public override ModelMetadata GetMetadataForParameter(ParameterInfo parameter) + { + var metadata = (DefaultModelMetadata)_innerProvider.GetMetadataForParameter(parameter); + + TurnOffConvertEmptyStringToNull(metadata); + + return metadata; + } + + public override ModelMetadata GetMetadataForParameter(ParameterInfo parameter, Type modelType) + { + return _innerProvider.GetMetadataForParameter(parameter, modelType); + } + + public override ModelMetadata GetMetadataForProperty(PropertyInfo propertyInfo, Type modelType) + { + return _innerProvider.GetMetadataForProperty(propertyInfo, modelType); + } + + public override ModelMetadata GetMetadataForConstructor(ConstructorInfo constructor, Type modelType) + { + return _innerProvider.GetMetadataForConstructor(constructor, modelType); + } + + private static void TurnOffConvertEmptyStringToNull(DefaultModelMetadata metadata) + { + // https://github.com/dotnet/aspnetcore/issues/29948#issuecomment-2058747809 + metadata.DisplayMetadata.ConvertEmptyStringToNull = false; + } + } +} diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/ZeroAsKeyTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/ZeroAsKeyTests.cs index 19baa0cf58..56b5be0e8c 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/ZeroAsKeyTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/ZeroAsKeyTests.cs @@ -30,7 +30,7 @@ public ZeroAsKeyTests(IntegrationTestContext, public async Task Can_filter_by_zero_ID_on_primary_resources() { // Arrange - List games = _fakers.Game.Generate(2); + List games = _fakers.Game.GenerateList(2); games[0].Id = 0; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -48,12 +48,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be("0"); responseDocument.Data.ManyValue[0].With(resource => { - resource.Links.ShouldNotBeNull(); + resource.Links.Should().NotBeNull(); resource.Links.Self.Should().Be("/games/0"); }); } @@ -62,9 +62,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_get_primary_resource_by_zero_ID_with_include() { // Arrange - Game game = _fakers.Game.Generate(); + Game game = _fakers.Game.GenerateOne(); game.Id = 0; - game.ActivePlayers = _fakers.Player.Generate(1); + game.ActivePlayers = _fakers.Player.GenerateList(1); await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -81,12 +81,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be("0"); - responseDocument.Data.SingleValue.Links.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Links.Should().NotBeNull(); responseDocument.Data.SingleValue.Links.Self.Should().Be("/games/0"); - responseDocument.Included.ShouldHaveCount(1); + responseDocument.Included.Should().HaveCount(1); responseDocument.Included[0].Id.Should().Be(game.ActivePlayers.ElementAt(0).StringId); } @@ -94,7 +94,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_create_resource_with_zero_ID() { // Arrange - string newTitle = _fakers.Game.Generate().Title; + string newTitle = _fakers.Game.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -124,14 +124,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => httpResponse.Headers.Location.Should().Be("/games/0"); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be("0"); await _testContext.RunOnDatabaseAsync(async dbContext => { Game gameInDatabase = await dbContext.Games.FirstWithIdAsync((int?)0); - gameInDatabase.ShouldNotBeNull(); + gameInDatabase.Should().NotBeNull(); gameInDatabase.Title.Should().Be(newTitle); }); } @@ -140,10 +140,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_update_resource_with_zero_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); existingGame.Id = 0; - string newTitle = _fakers.Game.Generate().Title; + string newTitle = _fakers.Game.GenerateOne().Title; await _testContext.RunOnDatabaseAsync(async dbContext => { @@ -173,15 +173,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be("0"); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("title").With(value => value.Should().Be(newTitle)); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("title").WhoseValue.Should().Be(newTitle); await _testContext.RunOnDatabaseAsync(async dbContext => { Game gameInDatabase = await dbContext.Games.FirstWithIdAsync((int?)0); - gameInDatabase.ShouldNotBeNull(); + gameInDatabase.Should().NotBeNull(); gameInDatabase.Title.Should().Be(newTitle); }); } @@ -190,8 +190,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_ToOne_relationship_with_zero_ID() { // Arrange - Player existingPlayer = _fakers.Player.Generate(); - existingPlayer.ActiveGame = _fakers.Game.Generate(); + Player existingPlayer = _fakers.Player.GenerateOne(); + existingPlayer.ActiveGame = _fakers.Game.GenerateOne(); existingPlayer.ActiveGame.Id = 0; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -220,7 +220,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Player playerInDatabase = await dbContext.Players.Include(player => player.ActiveGame).FirstWithIdAsync(existingPlayer.Id); - playerInDatabase.ShouldNotBeNull(); + playerInDatabase.Should().NotBeNull(); playerInDatabase.ActiveGame.Should().BeNull(); }); } @@ -229,9 +229,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_assign_ToOne_relationship_with_zero_ID() { // Arrange - Player existingPlayer = _fakers.Player.Generate(); + Player existingPlayer = _fakers.Player.GenerateOne(); - Game existingGame = _fakers.Game.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); existingGame.Id = 0; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -264,8 +264,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Player playerInDatabase = await dbContext.Players.Include(player => player.ActiveGame).FirstWithIdAsync(existingPlayer.Id); - playerInDatabase.ShouldNotBeNull(); - playerInDatabase.ActiveGame.ShouldNotBeNull(); + playerInDatabase.Should().NotBeNull(); + playerInDatabase.ActiveGame.Should().NotBeNull(); playerInDatabase.ActiveGame.Id.Should().Be(0); }); } @@ -274,10 +274,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ToOne_relationship_with_zero_ID() { // Arrange - Player existingPlayer = _fakers.Player.Generate(); - existingPlayer.ActiveGame = _fakers.Game.Generate(); + Player existingPlayer = _fakers.Player.GenerateOne(); + existingPlayer.ActiveGame = _fakers.Game.GenerateOne(); - Game existingGame = _fakers.Game.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); existingGame.Id = 0; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -310,8 +310,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Player playerInDatabase = await dbContext.Players.Include(player => player.ActiveGame).FirstWithIdAsync(existingPlayer.Id); - playerInDatabase.ShouldNotBeNull(); - playerInDatabase.ActiveGame.ShouldNotBeNull(); + playerInDatabase.Should().NotBeNull(); + playerInDatabase.ActiveGame.Should().NotBeNull(); playerInDatabase.ActiveGame.Id.Should().Be(0); }); } @@ -320,8 +320,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_clear_ToMany_relationship_with_zero_ID() { // Arrange - Player existingPlayer = _fakers.Player.Generate(); - existingPlayer.RecentlyPlayed = _fakers.Game.Generate(2); + Player existingPlayer = _fakers.Player.GenerateOne(); + existingPlayer.RecentlyPlayed = _fakers.Game.GenerateList(2); existingPlayer.RecentlyPlayed.ElementAt(0).Id = 0; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -350,7 +350,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Player playerInDatabase = await dbContext.Players.Include(player => player.RecentlyPlayed).FirstWithIdAsync(existingPlayer.Id); - playerInDatabase.ShouldNotBeNull(); + playerInDatabase.Should().NotBeNull(); playerInDatabase.RecentlyPlayed.Should().BeEmpty(); }); } @@ -359,9 +359,9 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_assign_ToMany_relationship_with_zero_ID() { // Arrange - Player existingPlayer = _fakers.Player.Generate(); + Player existingPlayer = _fakers.Player.GenerateOne(); - Game existingGame = _fakers.Game.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); existingGame.Id = 0; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -397,8 +397,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Player playerInDatabase = await dbContext.Players.Include(player => player.RecentlyPlayed).FirstWithIdAsync(existingPlayer.Id); - playerInDatabase.ShouldNotBeNull(); - playerInDatabase.RecentlyPlayed.ShouldHaveCount(1); + playerInDatabase.Should().NotBeNull(); + playerInDatabase.RecentlyPlayed.Should().HaveCount(1); playerInDatabase.RecentlyPlayed.ElementAt(0).Id.Should().Be(0); }); } @@ -407,10 +407,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_replace_ToMany_relationship_with_zero_ID() { // Arrange - Player existingPlayer = _fakers.Player.Generate(); - existingPlayer.RecentlyPlayed = _fakers.Game.Generate(2); + Player existingPlayer = _fakers.Player.GenerateOne(); + existingPlayer.RecentlyPlayed = _fakers.Game.GenerateList(2); - Game existingGame = _fakers.Game.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); existingGame.Id = 0; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -446,8 +446,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Player playerInDatabase = await dbContext.Players.Include(player => player.RecentlyPlayed).FirstWithIdAsync(existingPlayer.Id); - playerInDatabase.ShouldNotBeNull(); - playerInDatabase.RecentlyPlayed.ShouldHaveCount(1); + playerInDatabase.Should().NotBeNull(); + playerInDatabase.RecentlyPlayed.Should().HaveCount(1); playerInDatabase.RecentlyPlayed.ElementAt(0).Id.Should().Be(0); }); } @@ -456,10 +456,10 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_add_to_ToMany_relationship_with_zero_ID() { // Arrange - Player existingPlayer = _fakers.Player.Generate(); - existingPlayer.RecentlyPlayed = _fakers.Game.Generate(1); + Player existingPlayer = _fakers.Player.GenerateOne(); + existingPlayer.RecentlyPlayed = _fakers.Game.GenerateList(1); - Game existingGame = _fakers.Game.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); existingGame.Id = 0; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -495,8 +495,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Player playerInDatabase = await dbContext.Players.Include(player => player.RecentlyPlayed).FirstWithIdAsync(existingPlayer.Id); - playerInDatabase.ShouldNotBeNull(); - playerInDatabase.RecentlyPlayed.ShouldHaveCount(2); + playerInDatabase.Should().NotBeNull(); + playerInDatabase.RecentlyPlayed.Should().HaveCount(2); playerInDatabase.RecentlyPlayed.Should().ContainSingle(game => game.Id == 0); }); } @@ -505,8 +505,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_remove_from_ToMany_relationship_with_zero_ID() { // Arrange - Player existingPlayer = _fakers.Player.Generate(); - existingPlayer.RecentlyPlayed = _fakers.Game.Generate(2); + Player existingPlayer = _fakers.Player.GenerateOne(); + existingPlayer.RecentlyPlayed = _fakers.Game.GenerateList(2); existingPlayer.RecentlyPlayed.ElementAt(0).Id = 0; await _testContext.RunOnDatabaseAsync(async dbContext => @@ -542,8 +542,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => { Player playerInDatabase = await dbContext.Players.Include(player => player.RecentlyPlayed).FirstWithIdAsync(existingPlayer.Id); - playerInDatabase.ShouldNotBeNull(); - playerInDatabase.RecentlyPlayed.ShouldHaveCount(1); + playerInDatabase.Should().NotBeNull(); + playerInDatabase.RecentlyPlayed.Should().HaveCount(1); playerInDatabase.RecentlyPlayed.Should().ContainSingle(game => game.Id != 0); }); } @@ -552,7 +552,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Can_delete_resource_with_zero_ID() { // Arrange - Game existingGame = _fakers.Game.Generate(); + Game existingGame = _fakers.Game.GenerateOne(); existingGame.Id = 0; await _testContext.RunOnDatabaseAsync(async dbContext => diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/ZeroKeyDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/ZeroKeyDbContext.cs index 8502500c20..836a4637dc 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/ZeroKeyDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/ZeroKeyDbContext.cs @@ -7,7 +7,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ZeroKeys; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -public sealed class ZeroKeyDbContext(DbContextOptions options) : TestableDbContext(options) +public sealed class ZeroKeyDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet Games => Set(); public DbSet Players => Set(); diff --git a/test/JsonApiDotNetCoreTests/JsonApiDotNetCoreTests.csproj b/test/JsonApiDotNetCoreTests/JsonApiDotNetCoreTests.csproj index 38d665aa5b..6bc5a666a1 100644 --- a/test/JsonApiDotNetCoreTests/JsonApiDotNetCoreTests.csproj +++ b/test/JsonApiDotNetCoreTests/JsonApiDotNetCoreTests.csproj @@ -1,6 +1,6 @@ - net8.0;net6.0 + net9.0;net8.0 @@ -13,7 +13,6 @@ - diff --git a/test/JsonApiDotNetCoreTests/UnitTests/Configuration/DependencyContainerRegistrationTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/Configuration/DependencyContainerRegistrationTests.cs index 1249cd5dfa..1bf13394b5 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/Configuration/DependencyContainerRegistrationTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/Configuration/DependencyContainerRegistrationTests.cs @@ -1,6 +1,5 @@ using FluentAssertions; using JetBrains.Annotations; -using JsonApiDotNetCore; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Controllers.Annotations; using JsonApiDotNetCore.Queries; @@ -148,7 +147,7 @@ private sealed class SomeSingletonService // ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local public SomeSingletonService(SomeScopedService scopedService) { - ArgumentGuard.NotNull(scopedService); + ArgumentNullException.ThrowIfNull(scopedService); } } @@ -161,7 +160,7 @@ private sealed class CircularServiceA // ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local public CircularServiceA(CircularServiceB serviceB) { - ArgumentGuard.NotNull(serviceB); + ArgumentNullException.ThrowIfNull(serviceB); } } @@ -171,7 +170,7 @@ private sealed class CircularServiceB // ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local public CircularServiceB(CircularServiceA serviceA) { - ArgumentGuard.NotNull(serviceA); + ArgumentNullException.ThrowIfNull(serviceA); } } diff --git a/test/JsonApiDotNetCoreTests/UnitTests/Configuration/ServiceCollectionExtensionsTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/Configuration/ServiceCollectionExtensionsTests.cs index 66bb8b6f04..55ff20306b 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/Configuration/ServiceCollectionExtensionsTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/Configuration/ServiceCollectionExtensionsTests.cs @@ -567,7 +567,8 @@ public void OnSerialize(ResourceOfGuid resource) } [UsedImplicitly(ImplicitUseTargetFlags.Members)] - private sealed class TestDbContext(DbContextOptions options) : TestableDbContext(options) + private sealed class TestDbContext(DbContextOptions options) + : TestableDbContext(options) { public DbSet ResourcesOfInt32 => Set(); public DbSet ResourcesOfGuid => Set(); diff --git a/test/JsonApiDotNetCoreTests/UnitTests/Controllers/DefaultOperationFilterTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/Controllers/DefaultOperationFilterTests.cs new file mode 100644 index 0000000000..66560fdf7b --- /dev/null +++ b/test/JsonApiDotNetCoreTests/UnitTests/Controllers/DefaultOperationFilterTests.cs @@ -0,0 +1,104 @@ +using FluentAssertions; +using JetBrains.Annotations; +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.Resources; +using Microsoft.Extensions.Logging.Abstractions; +using Xunit; + +namespace JsonApiDotNetCoreTests.UnitTests.Controllers; + +public sealed class DefaultOperationFilterTests +{ + // @formatter:wrap_chained_method_calls chop_always + // @formatter:wrap_before_first_method_call true + + private static readonly IResourceGraph ResourceGraph = new ResourceGraphBuilder(new JsonApiOptions(), NullLoggerFactory.Instance) + .Add() + .Add() + .Add() + .Build(); + + // @formatter:wrap_before_first_method_call restore + // @formatter:wrap_chained_method_calls restore + + [Theory] + [InlineData(WriteOperationKind.CreateResource)] + [InlineData(WriteOperationKind.UpdateResource)] + [InlineData(WriteOperationKind.DeleteResource)] + [InlineData(WriteOperationKind.SetRelationship)] + [InlineData(WriteOperationKind.AddToRelationship)] + [InlineData(WriteOperationKind.RemoveFromRelationship)] + public void Operations_enabled_on_abstract_base_type_are_implicitly_enabled_on_derived_types(WriteOperationKind writeOperation) + { + // Arrange + ResourceType abstractBaseType = ResourceGraph.GetResourceType(); + ResourceType concreteBaseType = ResourceGraph.GetResourceType(); + ResourceType concreteDerivedType = ResourceGraph.GetResourceType(); + + var filter = new FakeOperationFilter(resourceType => resourceType.Equals(abstractBaseType)); + + // Act + bool abstractBaseIsEnabled = filter.IsEnabled(abstractBaseType, writeOperation); + bool concreteBaseIsEnabled = filter.IsEnabled(concreteBaseType, writeOperation); + bool concreteDerivedIsEnabled = filter.IsEnabled(concreteDerivedType, writeOperation); + + // Assert + abstractBaseIsEnabled.Should().BeTrue(); + concreteBaseIsEnabled.Should().BeTrue(); + concreteDerivedIsEnabled.Should().BeTrue(); + } + + [Theory] + [InlineData(WriteOperationKind.CreateResource)] + [InlineData(WriteOperationKind.UpdateResource)] + [InlineData(WriteOperationKind.DeleteResource)] + [InlineData(WriteOperationKind.SetRelationship)] + [InlineData(WriteOperationKind.AddToRelationship)] + [InlineData(WriteOperationKind.RemoveFromRelationship)] + public void Operations_enabled_on_concrete_base_type_are_implicitly_enabled_on_derived_types(WriteOperationKind writeOperation) + { + // Arrange + ResourceType abstractBaseType = ResourceGraph.GetResourceType(); + ResourceType concreteBaseType = ResourceGraph.GetResourceType(); + ResourceType concreteDerivedType = ResourceGraph.GetResourceType(); + + var filter = new FakeOperationFilter(resourceType => resourceType.Equals(concreteBaseType)); + + // Act + bool abstractBaseIsEnabled = filter.IsEnabled(abstractBaseType, writeOperation); + bool concreteBaseIsEnabled = filter.IsEnabled(concreteBaseType, writeOperation); + bool concreteDerivedIsEnabled = filter.IsEnabled(concreteDerivedType, writeOperation); + + // Assert + abstractBaseIsEnabled.Should().BeFalse(); + concreteBaseIsEnabled.Should().BeTrue(); + concreteDerivedIsEnabled.Should().BeTrue(); + } + + private sealed class FakeOperationFilter : DefaultOperationFilter + { + private readonly Func _isResourceTypeEnabled; + + public FakeOperationFilter(Func isResourceTypeEnabled) + { + ArgumentNullException.ThrowIfNull(isResourceTypeEnabled); + + _isResourceTypeEnabled = isResourceTypeEnabled; + } + + protected override JsonApiEndpoints? GetJsonApiEndpoints(ResourceType resourceType) + { + return _isResourceTypeEnabled(resourceType) ? JsonApiEndpoints.All : JsonApiEndpoints.None; + } + } + + private abstract class AbstractBaseType : Identifiable; + + private class ConcreteBaseType : AbstractBaseType; + + [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] + private sealed class ConcreteDerivedType : ConcreteBaseType; +} diff --git a/test/JsonApiDotNetCoreTests/UnitTests/Controllers/GetJsonApiEndpointTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/Controllers/GetJsonApiEndpointTests.cs new file mode 100644 index 0000000000..f78edebe49 --- /dev/null +++ b/test/JsonApiDotNetCoreTests/UnitTests/Controllers/GetJsonApiEndpointTests.cs @@ -0,0 +1,43 @@ +using FluentAssertions; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Routing; +using Xunit; + +namespace JsonApiDotNetCoreTests.UnitTests.Controllers; + +public sealed class GetJsonApiEndpointTests +{ + [Theory] + [InlineData("GET", null, JsonApiEndpoints.GetCollection)] + [InlineData("GET", "{id}", JsonApiEndpoints.GetSingle)] + [InlineData("GET", "{id}/{relationshipName}", JsonApiEndpoints.GetSecondary)] + [InlineData("GET", "{id}/relationships/{relationshipName}", JsonApiEndpoints.GetRelationship)] + [InlineData("POST", null, JsonApiEndpoints.Post)] + [InlineData("POST", "{id}/relationships/{relationshipName}", JsonApiEndpoints.PostRelationship)] + [InlineData("PATCH", "{id}", JsonApiEndpoints.Patch)] + [InlineData("PATCH", "{id}/relationships/{relationshipName}", JsonApiEndpoints.PatchRelationship)] + [InlineData("DELETE", "{id}", JsonApiEndpoints.Delete)] + [InlineData("DELETE", "{id}/relationships/{relationshipName}", JsonApiEndpoints.DeleteRelationship)] + [InlineData("PUT", null, JsonApiEndpoints.None)] + public void Can_identify_endpoint_from_http_method_and_route_template(string httpMethod, string? routeTemplate, JsonApiEndpoints expected) + { + // Arrange + HttpMethodAttribute attribute = httpMethod switch + { + "GET" => routeTemplate == null ? new HttpGetAttribute() : new HttpGetAttribute(routeTemplate), + "POST" => routeTemplate == null ? new HttpPostAttribute() : new HttpPostAttribute(routeTemplate), + "PATCH" => routeTemplate == null ? new HttpPatchAttribute() : new HttpPatchAttribute(routeTemplate), + "DELETE" => routeTemplate == null ? new HttpDeleteAttribute() : new HttpDeleteAttribute(routeTemplate), + "PUT" => routeTemplate == null ? new HttpPutAttribute() : new HttpPutAttribute(routeTemplate), + _ => throw new ArgumentOutOfRangeException(nameof(httpMethod), httpMethod, null) + }; + + // Act + JsonApiEndpoints endpoint = HttpMethodAttributeExtensions.GetJsonApiEndpoint([attribute]); + + // Assert + endpoint.Should().Be(expected); + } +} diff --git a/test/JsonApiDotNetCoreTests/UnitTests/FieldChains/FieldChainPatternInheritanceMatchTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/FieldChains/FieldChainPatternInheritanceMatchTests.cs index 067f8167d8..f5cd78f6ff 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/FieldChains/FieldChainPatternInheritanceMatchTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/FieldChains/FieldChainPatternInheritanceMatchTests.cs @@ -15,7 +15,7 @@ namespace JsonApiDotNetCoreTests.UnitTests.FieldChains; -public sealed class FieldChainPatternInheritanceMatchTests +public sealed class FieldChainPatternInheritanceMatchTests : IDisposable { private const string TBase = "bases"; private const string TDerivedQ = "derivedQs"; @@ -42,8 +42,13 @@ public sealed class FieldChainPatternInheritanceMatchTests public FieldChainPatternInheritanceMatchTests(ITestOutputHelper testOutputHelper) { +#pragma warning disable CA2000 // Dispose objects before losing scope + // Justification: LoggerFactory.AddProvider takes ownership (passing the provider as a constructor parameter does not). var loggerProvider = new XUnitLoggerProvider(testOutputHelper, null, LogOutputFields.Message); - _loggerFactory = new LoggerFactory([loggerProvider]); +#pragma warning restore CA2000 // Dispose objects before losing scope + + _loggerFactory = new LoggerFactory(); + _loggerFactory.AddProvider(loggerProvider); var options = new JsonApiOptions(); _resourceGraph = new ResourceGraphBuilder(options, NullLoggerFactory.Instance).Add().Add().Add().Build(); @@ -156,6 +161,11 @@ public void MatchFails(string patternText, string resourceTypeName, string field result.IsSuccess.Should().BeFalse(); } + public void Dispose() + { + _loggerFactory.Dispose(); + } + [UsedImplicitly(ImplicitUseTargetFlags.Members)] private abstract class Base : Identifiable { diff --git a/test/JsonApiDotNetCoreTests/UnitTests/FieldChains/FieldChainPatternMatchTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/FieldChains/FieldChainPatternMatchTests.cs index 613dd4fd41..948ce73ff3 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/FieldChains/FieldChainPatternMatchTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/FieldChains/FieldChainPatternMatchTests.cs @@ -15,7 +15,7 @@ namespace JsonApiDotNetCoreTests.UnitTests.FieldChains; -public sealed class FieldChainPatternMatchTests +public sealed class FieldChainPatternMatchTests : IDisposable { private const string T = "resources"; private const string X = "unknown"; @@ -28,8 +28,13 @@ public sealed class FieldChainPatternMatchTests public FieldChainPatternMatchTests(ITestOutputHelper testOutputHelper) { +#pragma warning disable CA2000 // Dispose objects before losing scope + // Justification: LoggerFactory.AddProvider takes ownership (passing the provider as a constructor parameter does not). var loggerProvider = new XUnitLoggerProvider(testOutputHelper, null, LogOutputFields.Message); - _loggerFactory = new LoggerFactory([loggerProvider]); +#pragma warning restore CA2000 // Dispose objects before losing scope + + _loggerFactory = new LoggerFactory(); + _loggerFactory.AddProvider(loggerProvider); var options = new JsonApiOptions(); IResourceGraph resourceGraph = new ResourceGraphBuilder(options, NullLoggerFactory.Instance).Add().Build(); @@ -399,6 +404,11 @@ public void MatchFails(string patternText, string fieldChainText, string failure result.IsSuccess.Should().BeFalse(); } + public void Dispose() + { + _loggerFactory.Dispose(); + } + [UsedImplicitly(ImplicitUseTargetFlags.Members)] private sealed class Resource : Identifiable { diff --git a/test/JsonApiDotNetCoreTests/UnitTests/Links/LinkInclusionTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/Links/LinkInclusionTests.cs index 9b8890618a..b6d7c8b618 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/Links/LinkInclusionTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/Links/LinkInclusionTests.cs @@ -10,7 +10,6 @@ using JsonApiDotNetCore.Serialization.Response; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; -using TestBuildingBlocks; using Xunit; namespace JsonApiDotNetCoreTests.UnitTests.Links; @@ -116,11 +115,11 @@ public void Applies_cascading_settings_for_top_level_links(LinkTypes linksInReso } else { - topLevelLinks.ShouldNotBeNull(); + topLevelLinks.Should().NotBeNull(); if (expected.HasFlag(LinkTypes.Self)) { - topLevelLinks.Self.ShouldNotBeNull(); + topLevelLinks.Self.Should().NotBeNull(); } else { @@ -129,7 +128,7 @@ public void Applies_cascading_settings_for_top_level_links(LinkTypes linksInReso if (expected.HasFlag(LinkTypes.Related)) { - topLevelLinks.Related.ShouldNotBeNull(); + topLevelLinks.Related.Should().NotBeNull(); } else { @@ -138,10 +137,10 @@ public void Applies_cascading_settings_for_top_level_links(LinkTypes linksInReso if (expected.HasFlag(LinkTypes.Pagination)) { - topLevelLinks.First.ShouldNotBeNull(); - topLevelLinks.Last.ShouldNotBeNull(); - topLevelLinks.Prev.ShouldNotBeNull(); - topLevelLinks.Next.ShouldNotBeNull(); + topLevelLinks.First.Should().NotBeNull(); + topLevelLinks.Last.Should().NotBeNull(); + topLevelLinks.Prev.Should().NotBeNull(); + topLevelLinks.Next.Should().NotBeNull(); } else { @@ -198,8 +197,8 @@ public void Applies_cascading_settings_for_resource_links(LinkTypes linksInResou // Assert if (expected == LinkTypes.Self) { - resourceLinks.ShouldNotBeNull(); - resourceLinks.Self.ShouldNotBeNull(); + resourceLinks.Should().NotBeNull(); + resourceLinks.Self.Should().NotBeNull(); } else { @@ -372,11 +371,11 @@ public void Applies_cascading_settings_for_relationship_links(LinkTypes linksInR } else { - relationshipLinks.ShouldNotBeNull(); + relationshipLinks.Should().NotBeNull(); if (expected.HasFlag(LinkTypes.Self)) { - relationshipLinks.Self.ShouldNotBeNull(); + relationshipLinks.Self.Should().NotBeNull(); } else { @@ -385,7 +384,7 @@ public void Applies_cascading_settings_for_relationship_links(LinkTypes linksInR if (expected.HasFlag(LinkTypes.Related)) { - relationshipLinks.Related.ShouldNotBeNull(); + relationshipLinks.Related.Should().NotBeNull(); } else { diff --git a/test/JsonApiDotNetCoreTests/UnitTests/Middleware/JsonApiMiddlewareTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/Middleware/JsonApiMiddlewareTests.cs index 196ac6493e..ad1f5df24f 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/Middleware/JsonApiMiddlewareTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/Middleware/JsonApiMiddlewareTests.cs @@ -7,10 +7,8 @@ using JsonApiDotNetCore.Resources.Annotations; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; -using Microsoft.AspNetCore.Mvc.ApplicationModels; using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.Extensions.Logging.Abstractions; -using TestBuildingBlocks; using Xunit; #pragma warning disable AV1561 // Signature contains too many parameters @@ -48,6 +46,8 @@ public async Task Sets_request_properties_correctly(string requestMethod, string { // Arrange var options = new JsonApiOptions(); + options.IncludeExtensions(JsonApiMediaTypeExtension.AtomicOperations); + var request = new JsonApiRequest(); // @formatter:wrap_chained_method_calls chop_always @@ -63,15 +63,20 @@ public async Task Sets_request_properties_correctly(string requestMethod, string // @formatter:wrap_chained_method_calls restore var httpContext = new DefaultHttpContext(); - IControllerResourceMapping controllerResourceMapping = SetupRoutes(httpContext, resourceGraph, requestMethod, requestPath); + FakeControllerResourceMapping controllerResourceMapping = SetupRoutes(httpContext, resourceGraph, requestMethod, requestPath); - var middleware = new JsonApiMiddleware(null, new HttpContextAccessor + var httpContextAccessor = new HttpContextAccessor { HttpContext = httpContext - }); + }; + + var contentNegotiator = new JsonApiContentNegotiator(options, httpContextAccessor); + + var middleware = new JsonApiMiddleware(null, httpContextAccessor, controllerResourceMapping, options, contentNegotiator, + NullLogger.Instance); // Act - await middleware.InvokeAsync(httpContext, controllerResourceMapping, options, request, NullLogger.Instance); + await middleware.InvokeAsync(httpContext, request); // Assert request.Kind.Should().Be(expectKind); @@ -83,7 +88,7 @@ public async Task Sets_request_properties_correctly(string requestMethod, string } else { - request.PrimaryResourceType.ShouldNotBeNull(); + request.PrimaryResourceType.Should().NotBeNull(); request.PrimaryResourceType.PublicName.Should().Be(expectPrimaryResourceType); } @@ -93,7 +98,7 @@ public async Task Sets_request_properties_correctly(string requestMethod, string } else { - request.SecondaryResourceType.ShouldNotBeNull(); + request.SecondaryResourceType.Should().NotBeNull(); request.SecondaryResourceType.PublicName.Should().Be(expectSecondaryResourceType); } @@ -103,7 +108,7 @@ public async Task Sets_request_properties_correctly(string requestMethod, string } else { - request.Relationship.ShouldNotBeNull(); + request.Relationship.Should().NotBeNull(); request.Relationship.PublicName.Should().Be(expectRelationshipName); } @@ -112,7 +117,7 @@ public async Task Sets_request_properties_correctly(string requestMethod, string request.WriteOperation.Should().Be(expectWriteOperation); } - private static IControllerResourceMapping SetupRoutes(HttpContext httpContext, IResourceGraph resourceGraph, string requestMethod, string requestPath) + private static FakeControllerResourceMapping SetupRoutes(HttpContext httpContext, IResourceGraph resourceGraph, string requestMethod, string requestPath) { httpContext.Request.Method = requestMethod; @@ -144,6 +149,7 @@ private static IControllerResourceMapping SetupRoutes(HttpContext httpContext, I else if (pathSegments.Contains("operations")) { feature.RouteValues["action"] = "PostOperations"; + httpContext.Request.Headers.Accept = JsonApiMediaType.AtomicOperations.ToString(); } httpContext.Features.Set(feature); @@ -156,7 +162,7 @@ private static IControllerResourceMapping SetupRoutes(HttpContext httpContext, I httpContext.SetEndpoint(new Endpoint(null, new EndpointMetadataCollection(controllerActionDescriptor), null)); string? resourceTypePublicName = pathSegments.Length > 0 ? pathSegments[0] : null; - return new FakeJsonApiRoutingConvention(resourceGraph, resourceTypePublicName); + return new FakeControllerResourceMapping(resourceGraph, resourceTypePublicName); } public enum IsReadOnly @@ -165,7 +171,9 @@ public enum IsReadOnly No } +#pragma warning disable CA1711 // Identifiers should not have incorrect suffix public enum IsCollection +#pragma warning restore CA1711 // Identifiers should not have incorrect suffix { Yes, No @@ -191,16 +199,11 @@ private sealed class TodoItem : Identifiable public ISet Tags { get; set; } = new HashSet(); } - private sealed class FakeJsonApiRoutingConvention(IResourceGraph resourceGraph, string? resourceTypePublicName) : IJsonApiRoutingConvention + private sealed class FakeControllerResourceMapping(IResourceGraph resourceGraph, string? resourceTypePublicName) : IControllerResourceMapping { private readonly IResourceGraph _resourceGraph = resourceGraph; private readonly string? _resourceTypePublicName = resourceTypePublicName; - public void Apply(ApplicationModel application) - { - throw new NotImplementedException(); - } - public ResourceType? GetResourceTypeForController(Type? controllerType) { return _resourceTypePublicName != null ? _resourceGraph.FindResourceType(_resourceTypePublicName) : null; diff --git a/test/JsonApiDotNetCoreTests/UnitTests/ModelStateValidation/ModelStateValidationTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/ModelStateValidation/ModelStateValidationTests.cs index 34bbc16d17..e3a0a26cd9 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/ModelStateValidation/ModelStateValidationTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/ModelStateValidation/ModelStateValidationTests.cs @@ -46,7 +46,7 @@ public void Renders_JSON_path_for_ModelState_key_in_resource_request(string mode var exception = new InvalidModelStateException(modelState, typeof(Parent), false, resourceGraph); // Assert - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); if (expectedJsonPath == null) { @@ -54,7 +54,7 @@ public void Renders_JSON_path_for_ModelState_key_in_resource_request(string mode } else { - exception.Errors[0].Source.ShouldNotBeNull().With(value => value.Pointer.Should().Be(expectedJsonPath)); + exception.Errors[0].Source.RefShould().NotBeNull().And.Subject.Pointer.Should().Be(expectedJsonPath); } } @@ -94,7 +94,7 @@ public void Renders_JSON_path_for_ModelState_key_in_operations_request(string mo var exception = new InvalidModelStateException(modelState, typeof(IList), false, resourceGraph, getOperationTypeCallback); // Assert - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); if (expectedJsonPath == null) { @@ -102,7 +102,7 @@ public void Renders_JSON_path_for_ModelState_key_in_operations_request(string mo } else { - exception.Errors[0].Source.ShouldNotBeNull().With(value => value.Pointer.Should().Be(expectedJsonPath)); + exception.Errors[0].Source.RefShould().NotBeNull().And.Subject.Pointer.Should().Be(expectedJsonPath); } } diff --git a/test/JsonApiDotNetCoreTests/UnitTests/Queries/QueryExpressionRewriterTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/Queries/QueryExpressionRewriterTests.cs index 3d2d8faa85..7f18610f89 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/Queries/QueryExpressionRewriterTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/Queries/QueryExpressionRewriterTests.cs @@ -52,11 +52,11 @@ public void VisitInclude(string expressionText, string expectedTypes) rewriter.Visit(expression, null); // Assert - List visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToList(); - List expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToList(); + string[] visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToArray(); + string[] expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToArray(); visitedTypeNames.Should().ContainInOrder(expectedTypeNames); - visitedTypeNames.Should().HaveCount(expectedTypeNames.Count); + visitedTypeNames.Should().HaveCount(expectedTypeNames.Length); } [Theory] @@ -75,11 +75,11 @@ public void VisitSparseFieldSet(string expressionText, string expectedTypes) rewriter.Visit(expression, null); // Assert - List visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToList(); - List expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToList(); + string[] visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToArray(); + string[] expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToArray(); visitedTypeNames.Should().ContainInOrder(expectedTypeNames); - visitedTypeNames.Should().HaveCount(expectedTypeNames.Count); + visitedTypeNames.Should().HaveCount(expectedTypeNames.Length); } [Fact] @@ -104,7 +104,7 @@ public void VisitSparseFieldTable() rewriter.Visit(expression, null); // Assert - List visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToList(); + string[] visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToArray(); visitedTypeNames.Should().HaveCount(3); visitedTypeNames[0].Should().Be("SparseFieldTableExpression"); @@ -135,11 +135,11 @@ public void VisitFilter(string expressionText, string expectedTypes) rewriter.Visit(expression, null); // Assert - List visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToList(); - List expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToList(); + string[] visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToArray(); + string[] expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToArray(); visitedTypeNames.Should().ContainInOrder(expectedTypeNames); - visitedTypeNames.Should().HaveCount(expectedTypeNames.Count); + visitedTypeNames.Should().HaveCount(expectedTypeNames.Length); } [Theory] @@ -159,11 +159,11 @@ public void VisitSort(string expressionText, string expectedTypes) rewriter.Visit(expression, null); // Assert - List visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToList(); - List expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToList(); + string[] visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToArray(); + string[] expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToArray(); visitedTypeNames.Should().ContainInOrder(expectedTypeNames); - visitedTypeNames.Should().HaveCount(expectedTypeNames.Count); + visitedTypeNames.Should().HaveCount(expectedTypeNames.Length); } [Theory] @@ -182,11 +182,11 @@ public void VisitPagination(string expressionText, string expectedTypes) rewriter.Visit(expression, null); // Assert - List visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToList(); - List expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToList(); + string[] visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToArray(); + string[] expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToArray(); visitedTypeNames.Should().ContainInOrder(expectedTypeNames); - visitedTypeNames.Should().HaveCount(expectedTypeNames.Count); + visitedTypeNames.Should().HaveCount(expectedTypeNames.Length); } [Theory] @@ -207,10 +207,10 @@ public void VisitParameterScope(string expressionText, string expectedTypes) rewriter.Visit(expression, null); // Assert - List visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToList(); - List expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToList(); + string[] visitedTypeNames = rewriter.ExpressionsVisited.Select(queryExpression => queryExpression.GetType().Name).ToArray(); + string[] expectedTypeNames = expectedTypes.Split(',').Select(type => $"{type}Expression").ToArray(); visitedTypeNames.Should().ContainInOrder(expectedTypeNames); - visitedTypeNames.Should().HaveCount(expectedTypeNames.Count); + visitedTypeNames.Should().HaveCount(expectedTypeNames.Length); } } diff --git a/test/JsonApiDotNetCoreTests/UnitTests/Queries/TestableQueryExpressionRewriter.cs b/test/JsonApiDotNetCoreTests/UnitTests/Queries/TestableQueryExpressionRewriter.cs index ec4da0702a..1f46516854 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/Queries/TestableQueryExpressionRewriter.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/Queries/TestableQueryExpressionRewriter.cs @@ -114,16 +114,16 @@ public override QueryExpression VisitSparseFieldSet(SparseFieldSetExpression exp return base.VisitQueryStringParameterScope(expression, argument); } - public override QueryExpression PaginationQueryStringValue(PaginationQueryStringValueExpression expression, object? argument) + public override QueryExpression VisitPaginationQueryStringValue(PaginationQueryStringValueExpression expression, object? argument) { Capture(expression); - return base.PaginationQueryStringValue(expression, argument); + return base.VisitPaginationQueryStringValue(expression, argument); } - public override QueryExpression PaginationElementQueryStringValue(PaginationElementQueryStringValueExpression expression, object? argument) + public override QueryExpression VisitPaginationElementQueryStringValue(PaginationElementQueryStringValueExpression expression, object? argument) { Capture(expression); - return base.PaginationElementQueryStringValue(expression, argument); + return base.VisitPaginationElementQueryStringValue(expression, argument); } public override QueryExpression VisitInclude(IncludeExpression expression, object? argument) diff --git a/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/FilterParseTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/FilterParseTests.cs index 9799d7d6ae..c9de843e56 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/FilterParseTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/FilterParseTests.cs @@ -22,7 +22,8 @@ public FilterParseTests() { Options.EnableLegacyFilterNotation = false; - var resourceFactory = new ResourceFactory(new ServiceContainer()); + using var serviceProvider = new ServiceContainer(); + var resourceFactory = new ResourceFactory(serviceProvider); var scopeParser = new QueryStringParameterScopeParser(); var valueParser = new FilterParser(resourceFactory); _reader = new FilterQueryStringParameterReader(scopeParser, valueParser, Request, ResourceGraph, Options); @@ -81,13 +82,13 @@ public void Reader_Read_ParameterName_Fails(string parameterName, string errorMe InvalidQueryStringParameterException exception = action.Should().ThrowExactly().And; exception.ParameterName.Should().Be(parameterNameSource.Text); - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); ErrorObject error = exception.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified filter is invalid."); error.Detail.Should().Be($"{errorMessage} {parameterNameSource}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be(parameterNameSource.Text); } @@ -158,13 +159,13 @@ public void Reader_Read_ParameterValue_Fails(string parameterName, string parame InvalidQueryStringParameterException exception = action.Should().ThrowExactly().And; exception.ParameterName.Should().Be(parameterName); - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); ErrorObject error = exception.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified filter is invalid."); error.Detail.Should().Be($"{errorMessage} {parameterValueSource}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be(parameterName); } @@ -221,7 +222,8 @@ public void Reader_Read_Succeeds(string parameterName, string parameterValue, st public void Throws_When_ResourceType_Scope_Not_Disposed() { // Arrange - var resourceFactory = new ResourceFactory(new ServiceContainer()); + using var serviceProvider = new ServiceContainer(); + var resourceFactory = new ResourceFactory(serviceProvider); var parser = new NotDisposingFilterParser(resourceFactory); // Act @@ -236,7 +238,8 @@ public void Throws_When_ResourceType_Scope_Not_Disposed() public void Throws_When_No_ResourceType_In_Scope() { // Arrange - var resourceFactory = new ResourceFactory(new ServiceContainer()); + using var serviceProvider = new ServiceContainer(); + var resourceFactory = new ResourceFactory(serviceProvider); var parser = new ResourceTypeAccessingFilterParser(resourceFactory); // Act @@ -246,7 +249,8 @@ public void Throws_When_No_ResourceType_In_Scope() action.Should().ThrowExactly().WithMessage("No resource type is currently in scope. Call Parse() first."); } - private sealed class NotDisposingFilterParser(IResourceFactory resourceFactory) : FilterParser(resourceFactory) + private sealed class NotDisposingFilterParser(IResourceFactory resourceFactory) + : FilterParser(resourceFactory) { protected override FilterExpression ParseFilter() { @@ -257,7 +261,8 @@ protected override FilterExpression ParseFilter() } } - private sealed class ResourceTypeAccessingFilterParser(IResourceFactory resourceFactory) : FilterParser(resourceFactory) + private sealed class ResourceTypeAccessingFilterParser(IResourceFactory resourceFactory) + : FilterParser(resourceFactory) { protected override void Tokenize(string source) { diff --git a/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/IncludeParseTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/IncludeParseTests.cs index 096f469952..49a1027fb6 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/IncludeParseTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/IncludeParseTests.cs @@ -74,13 +74,13 @@ public void Reader_Read_Fails(string parameterName, string parameterValue, strin InvalidQueryStringParameterException exception = action.Should().ThrowExactly().And; exception.ParameterName.Should().Be(parameterName); - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); ErrorObject error = exception.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified include is invalid."); error.Detail.Should().Be($"{errorMessage} {parameterValueSource}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be(parameterName); } @@ -93,9 +93,9 @@ public void Reader_Read_Fails(string parameterName, string parameterValue, strin [InlineData("includes", "posts.comments", "posts.comments")] [InlineData("includes", "posts,posts.comments", "posts.comments")] [InlineData("includes", "posts,posts.labels,posts.comments", "posts.comments,posts.labels")] - [InlineData("includes", "owner.person.children.husband", "owner.person.children.husband")] + [InlineData("includes", "owner.person.children.husband", "owner.person.children.husband,owner.person.children.husband")] [InlineData("includes", "owner.person.wife,owner.person.husband", "owner.person.husband,owner.person.wife")] - [InlineData("includes", "owner.person.father.children.wife", "owner.person.father.children.wife")] + [InlineData("includes", "owner.person.father.children.wife", "owner.person.father.children.wife,owner.person.father.children.wife")] [InlineData("includes", "owner.person.friends", "owner.person.friends,owner.person.friends")] [InlineData("includes", "owner.person.friends.friends", "owner.person.friends.friends,owner.person.friends.friends,owner.person.friends.friends,owner.person.friends.friends")] diff --git a/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/LegacyFilterParseTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/LegacyFilterParseTests.cs index 2fcc490d1e..eae586ebdb 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/LegacyFilterParseTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/LegacyFilterParseTests.cs @@ -9,7 +9,6 @@ using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Serialization.Objects; using JsonApiDotNetCoreTests.IntegrationTests.QueryStrings; -using TestBuildingBlocks; using Xunit; namespace JsonApiDotNetCoreTests.UnitTests.QueryStringParameters; @@ -24,7 +23,8 @@ public LegacyFilterParseTests() Request.PrimaryResourceType = ResourceGraph.GetResourceType(); - var resourceFactory = new ResourceFactory(new ServiceContainer()); + using var serviceProvider = new ServiceContainer(); + var resourceFactory = new ResourceFactory(serviceProvider); var scopeParser = new QueryStringParameterScopeParser(); var valueParser = new FilterParser(resourceFactory); _reader = new FilterQueryStringParameterReader(scopeParser, valueParser, Request, ResourceGraph, Options); @@ -48,13 +48,13 @@ public void Reader_Read_ParameterName_Fails(string parameterName, string errorMe InvalidQueryStringParameterException exception = action.Should().ThrowExactly().And; exception.ParameterName.Should().Be(parameterName); - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); ErrorObject error = exception.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified filter is invalid."); error.Detail.Should().Be(errorMessage); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be(parameterName); } @@ -77,13 +77,13 @@ public void Reader_Read_ParameterValue_Fails(string parameterName, string parame InvalidQueryStringParameterException exception = action.Should().ThrowExactly().And; exception.ParameterName.Should().Be(parameterName); - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); ErrorObject error = exception.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified filter is invalid."); error.Detail.Should().Be(errorMessage); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be(parameterName); } diff --git a/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/PaginationParseTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/PaginationParseTests.cs index f98ff59f59..8020bbb01c 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/PaginationParseTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/PaginationParseTests.cs @@ -15,7 +15,7 @@ namespace JsonApiDotNetCoreTests.UnitTests.QueryStringParameters; public sealed class PaginationParseTests : BaseParseTests { - private readonly IPaginationQueryStringParameterReader _reader; + private readonly PaginationQueryStringParameterReader _reader; public PaginationParseTests() { @@ -89,13 +89,13 @@ public void Reader_Read_Page_Number_Fails(string parameterValue, string errorMes InvalidQueryStringParameterException exception = action.Should().ThrowExactly().And; exception.ParameterName.Should().Be("page[number]"); - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); ErrorObject error = exception.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified pagination is invalid."); error.Detail.Should().Be($"{errorMessage} {parameterValueSource}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("page[number]"); } @@ -134,13 +134,13 @@ public void Reader_Read_Page_Size_Fails(string parameterValue, string errorMessa InvalidQueryStringParameterException exception = action.Should().ThrowExactly().And; exception.ParameterName.Should().Be("page[size]"); - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); ErrorObject error = exception.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified pagination is invalid."); error.Detail.Should().Be($"{errorMessage} {parameterValueSource}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be("page[size]"); } diff --git a/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/SortParseTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/SortParseTests.cs index 77c52b3828..24832cbc7d 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/SortParseTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/SortParseTests.cs @@ -74,13 +74,13 @@ public void Reader_Read_ParameterName_Fails(string parameterName, string errorMe InvalidQueryStringParameterException exception = action.Should().ThrowExactly().And; exception.ParameterName.Should().Be(parameterNameSource.Text); - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); ErrorObject error = exception.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified sort is invalid."); error.Detail.Should().Be($"{errorMessage} {parameterNameSource}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be(parameterNameSource.Text); } @@ -126,13 +126,13 @@ public void Reader_Read_ParameterValue_Fails(string parameterName, string parame InvalidQueryStringParameterException exception = action.Should().ThrowExactly().And; exception.ParameterName.Should().Be(parameterName); - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); ErrorObject error = exception.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified sort is invalid."); error.Detail.Should().Be($"{errorMessage} {parameterValueSource}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be(parameterName); } diff --git a/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/SparseFieldSetParseTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/SparseFieldSetParseTests.cs index 51906bb613..19991bacae 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/SparseFieldSetParseTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/SparseFieldSetParseTests.cs @@ -73,13 +73,13 @@ public void Reader_Read_ParameterName_Fails(string parameterName, string errorMe InvalidQueryStringParameterException exception = action.Should().ThrowExactly().And; exception.ParameterName.Should().Be(parameterNameSource.Text); - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); ErrorObject error = exception.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified fieldset is invalid."); error.Detail.Should().Be($"{errorMessage} {parameterNameSource}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be(parameterNameSource.Text); } @@ -103,13 +103,13 @@ public void Reader_Read_ParameterValue_Fails(string parameterName, string parame InvalidQueryStringParameterException exception = action.Should().ThrowExactly().And; exception.ParameterName.Should().Be(parameterName); - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); ErrorObject error = exception.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.BadRequest); error.Title.Should().Be("The specified fieldset is invalid."); error.Detail.Should().Be($"{errorMessage} {parameterValueSource}"); - error.Source.ShouldNotBeNull(); + error.Source.Should().NotBeNull(); error.Source.Parameter.Should().Be(parameterName); } diff --git a/test/JsonApiDotNetCoreTests/UnitTests/ResourceDefinitions/CreateSortExpressionFromLambdaTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/ResourceDefinitions/CreateSortExpressionFromLambdaTests.cs index 30e8a899dc..dc59dbe907 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/ResourceDefinitions/CreateSortExpressionFromLambdaTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/ResourceDefinitions/CreateSortExpressionFromLambdaTests.cs @@ -8,7 +8,6 @@ using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; using Microsoft.Extensions.Logging.Abstractions; -using TestBuildingBlocks; using Xunit; namespace JsonApiDotNetCoreTests.UnitTests.ResourceDefinitions; @@ -120,7 +119,7 @@ public void Cannot_convert_unexposed_attribute() // Assert JsonApiException exception = action.Should().ThrowExactly().Which; - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); exception.Errors[0].StatusCode.Should().Be(HttpStatusCode.InternalServerError); exception.Errors[0].Title.Should().StartWith("Invalid lambda expression for sorting from resource definition. It should "); exception.Errors[0].Detail.Should().StartWith("The lambda expression 'file => Convert(file.IsCompressed, Object)' is invalid. "); @@ -142,7 +141,7 @@ public void Cannot_convert_unexposed_ToMany_relationship() // Assert JsonApiException exception = action.Should().ThrowExactly().Which; - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); exception.Errors[0].StatusCode.Should().Be(HttpStatusCode.InternalServerError); exception.Errors[0].Title.Should().StartWith("Invalid lambda expression for sorting from resource definition. It should "); exception.Errors[0].Detail.Should().StartWith("The lambda expression 'file => Convert(file.Content.Length, Object)' is invalid. "); @@ -164,7 +163,7 @@ public void Cannot_convert_unexposed_ToOne_relationship() // Assert JsonApiException exception = action.Should().ThrowExactly().Which; - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); exception.Errors[0].StatusCode.Should().Be(HttpStatusCode.InternalServerError); exception.Errors[0].Title.Should().StartWith("Invalid lambda expression for sorting from resource definition. It should "); exception.Errors[0].Detail.Should().StartWith("The lambda expression 'file => file.ParentDirectory.Name' is invalid. "); @@ -186,7 +185,7 @@ public void Cannot_convert_unexposed_resource_type() // Assert JsonApiException exception = action.Should().ThrowExactly().Which; - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); exception.Errors[0].StatusCode.Should().Be(HttpStatusCode.InternalServerError); exception.Errors[0].Title.Should().StartWith("Invalid lambda expression for sorting from resource definition. It should "); exception.Errors[0].Detail.Should().StartWith("The lambda expression 'entry => Convert(entry, FileEntry).Content' is invalid. "); @@ -208,7 +207,7 @@ public void Cannot_convert_count_with_predicate() // Assert JsonApiException exception = action.Should().ThrowExactly().Which; - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); exception.Errors[0].StatusCode.Should().Be(HttpStatusCode.InternalServerError); exception.Errors[0].Title.Should().StartWith("Invalid lambda expression for sorting from resource definition. It should "); exception.Errors[0].Detail.Should().StartWith("The lambda expression 'directory => Convert(directory.Files.Count(_ => True), Object)' is invalid. "); @@ -230,7 +229,7 @@ public void Cannot_convert_null_selector() // Assert JsonApiException exception = action.Should().ThrowExactly().Which; - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); exception.Errors[0].StatusCode.Should().Be(HttpStatusCode.InternalServerError); exception.Errors[0].Title.Should().StartWith("Invalid lambda expression for sorting from resource definition. It should "); exception.Errors[0].Detail.Should().Be("The lambda expression '_ => null' is invalid. Unsupported expression body 'null'."); @@ -251,7 +250,7 @@ public void Cannot_convert_self_selector() // Assert JsonApiException exception = action.Should().ThrowExactly().Which; - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); exception.Errors[0].StatusCode.Should().Be(HttpStatusCode.InternalServerError); exception.Errors[0].Title.Should().StartWith("Invalid lambda expression for sorting from resource definition. It should "); exception.Errors[0].Detail.Should().Be("The lambda expression 'entry => entry' is invalid. Unsupported expression body 'entry'."); @@ -273,7 +272,7 @@ public void Cannot_convert_conditional_operator() // Assert JsonApiException exception = action.Should().ThrowExactly().Which; - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); exception.Errors[0].StatusCode.Should().Be(HttpStatusCode.InternalServerError); exception.Errors[0].Title.Should().StartWith("Invalid lambda expression for sorting from resource definition. It should "); exception.Errors[0].Detail.Should().Match("The lambda expression '*' is invalid. Unsupported expression body '*'."); @@ -294,7 +293,7 @@ public void Cannot_convert_concatenation_operator() // Assert JsonApiException exception = action.Should().ThrowExactly().Which; - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); exception.Errors[0].StatusCode.Should().Be(HttpStatusCode.InternalServerError); exception.Errors[0].Title.Should().StartWith("Invalid lambda expression for sorting from resource definition. It should "); exception.Errors[0].Detail.Should().Match("The lambda expression '*' is invalid. Unsupported expression body '*'."); @@ -321,7 +320,7 @@ public void Cannot_convert_projection_into_anonymous_type() // Assert JsonApiException exception = action.Should().ThrowExactly().Which; - exception.Errors.ShouldHaveCount(1); + exception.Errors.Should().HaveCount(1); exception.Errors[0].StatusCode.Should().Be(HttpStatusCode.InternalServerError); exception.Errors[0].Title.Should().StartWith("Invalid lambda expression for sorting from resource definition. It should "); exception.Errors[0].Detail.Should().Match("The lambda expression '*' is invalid. Unsupported expression body '*'."); @@ -345,7 +344,8 @@ private static IResourceGraph GetResourceGraph() // @formatter:wrap_before_first_method_call restore } - private sealed class WrapperResourceDefinition(IResourceGraph resourceGraph) : JsonApiResourceDefinition(resourceGraph) + private sealed class WrapperResourceDefinition(IResourceGraph resourceGraph) + : JsonApiResourceDefinition(resourceGraph) where TResource : class, IIdentifiable { public SortExpression GetSortExpressionFromLambda(PropertySortOrder sortOrder) @@ -364,17 +364,17 @@ private abstract class FileSystemEntry : Identifiable public FileSystemEntry Parent { get; set; } = null!; [HasMany] - public IList Children { get; set; } = new List(); + public List Children { get; set; } = []; } [UsedImplicitly(ImplicitUseTargetFlags.Members)] private sealed class DirectoryEntry : FileSystemEntry { [HasMany] - public IList Subdirectories { get; set; } = new List(); + public List Subdirectories { get; set; } = []; [HasMany] - public IList Files { get; set; } = new List(); + public List Files { get; set; } = []; } [UsedImplicitly(ImplicitUseTargetFlags.Members)] diff --git a/test/JsonApiDotNetCoreTests/UnitTests/ResourceGraph/HasManyAttributeTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/ResourceGraph/HasManyAttributeTests.cs index 34ca2ef259..4a9d05f4dc 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/ResourceGraph/HasManyAttributeTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/ResourceGraph/HasManyAttributeTests.cs @@ -1,7 +1,6 @@ using FluentAssertions; using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; -using TestBuildingBlocks; using Xunit; namespace JsonApiDotNetCoreTests.UnitTests.ResourceGraph; @@ -73,16 +72,13 @@ public void Can_set_value_to_collection_with_single_resource() var resource = new TestResource(); - var children = new List - { - resource - }; + List children = [resource]; // Act attribute.SetValue(resource, children); // Assert - attribute.GetValue(resource).Should().BeOfType>().Subject.ShouldHaveCount(1); + attribute.GetValue(resource).Should().BeOfType>().Subject.Should().HaveCount(1); } [Fact] @@ -96,11 +92,11 @@ public void Cannot_set_value_to_collection_with_null_element() var resource = new TestResource(); - var children = new List - { + List children = + [ resource, null! - }; + ]; // Act Action action = () => attribute.SetValue(resource, children); @@ -120,11 +116,11 @@ public void Cannot_set_value_to_collection_with_primitive_element() var resource = new TestResource(); - var children = new List - { + List children = + [ resource, 1 - }; + ]; // Act Action action = () => attribute.SetValue(resource, children); @@ -157,7 +153,7 @@ public void Can_add_value_to_List() // Assert List collection = attribute.GetValue(resource).Should().BeOfType>().Subject!; - collection.ShouldHaveCount(2); + collection.Should().HaveCount(2); } [Fact] @@ -184,7 +180,7 @@ public void Can_add_existing_value_to_List() // Assert List collection = attribute.GetValue(resource).Should().BeOfType>().Subject!; - collection.ShouldHaveCount(1); + collection.Should().HaveCount(1); } [Fact] @@ -211,7 +207,7 @@ public void Can_add_value_to_HashSet() // Assert HashSet collection = attribute.GetValue(resource).Should().BeOfType>().Subject!; - collection.ShouldHaveCount(2); + collection.Should().HaveCount(2); } [Fact] @@ -238,7 +234,7 @@ public void Can_add_existing_value_to_HashSet() // Assert HashSet collection = attribute.GetValue(resource).Should().BeOfType>().Subject!; - collection.ShouldHaveCount(1); + collection.Should().HaveCount(1); } [Fact] @@ -262,7 +258,7 @@ public void Can_add_value_to_null_collection() // Assert HashSet collection = attribute.GetValue(resource).Should().BeOfType>().Subject!; - collection.ShouldHaveCount(1); + collection.Should().HaveCount(1); } public sealed class TestResource : Identifiable diff --git a/test/JsonApiDotNetCoreTests/UnitTests/ResourceGraph/ResourceGraphBuilderTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/ResourceGraph/ResourceGraphBuilderTests.cs index ebce906b9d..8288595662 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/ResourceGraph/ResourceGraphBuilderTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/ResourceGraph/ResourceGraphBuilderTests.cs @@ -256,15 +256,16 @@ public void Logs_warning_when_adding_non_resource_type() { // Arrange var options = new JsonApiOptions(); - var loggerFactory = new FakeLoggerFactory(LogLevel.Warning); + using var loggerProvider = new CapturingLoggerProvider(LogLevel.Warning); + using var loggerFactory = new LoggerFactory([loggerProvider]); var builder = new ResourceGraphBuilder(options, loggerFactory); // Act builder.Add(typeof(NonResource)); // Assert - IReadOnlyList logLines = loggerFactory.Logger.GetLines(); - logLines.ShouldHaveCount(1); + IReadOnlyList logLines = loggerProvider.GetLines(); + logLines.Should().HaveCount(1); logLines[0].Should().Be( $"[WARNING] Skipping: Type '{typeof(NonResource)}' does not implement 'IIdentifiable'. Add [NoResource] to suppress this warning."); @@ -275,14 +276,15 @@ public void Logs_no_warning_when_adding_non_resource_type_with_suppression() { // Arrange var options = new JsonApiOptions(); - var loggerFactory = new FakeLoggerFactory(LogLevel.Warning); + using var loggerProvider = new CapturingLoggerProvider(LogLevel.Warning); + using var loggerFactory = new LoggerFactory([loggerProvider]); var builder = new ResourceGraphBuilder(options, loggerFactory); // Act builder.Add(typeof(NonResourceWithSuppression)); // Assert - IReadOnlyList logLines = loggerFactory.Logger.GetLines(); + IReadOnlyList logLines = loggerProvider.GetLines(); logLines.Should().BeEmpty(); } @@ -291,15 +293,16 @@ public void Logs_warning_when_adding_resource_without_attributes() { // Arrange var options = new JsonApiOptions(); - var loggerFactory = new FakeLoggerFactory(LogLevel.Warning); + using var loggerProvider = new CapturingLoggerProvider(LogLevel.Warning); + using var loggerFactory = new LoggerFactory([loggerProvider]); var builder = new ResourceGraphBuilder(options, loggerFactory); // Act builder.Add(); // Assert - IReadOnlyList logLines = loggerFactory.Logger.GetLines(); - logLines.ShouldHaveCount(1); + IReadOnlyList logLines = loggerProvider.GetLines(); + logLines.Should().HaveCount(1); logLines[0].Should().Be($"[WARNING] Type '{typeof(ResourceWithHasOneRelationship)}' does not contain any attributes."); } @@ -309,15 +312,16 @@ public void Logs_warning_on_empty_graph() { // Arrange var options = new JsonApiOptions(); - var loggerFactory = new FakeLoggerFactory(LogLevel.Warning); + using var loggerProvider = new CapturingLoggerProvider(LogLevel.Warning); + using var loggerFactory = new LoggerFactory([loggerProvider]); var builder = new ResourceGraphBuilder(options, loggerFactory); // Act builder.Build(); // Assert - IReadOnlyList logLines = loggerFactory.Logger.GetLines(); - logLines.ShouldHaveCount(1); + IReadOnlyList logLines = loggerProvider.GetLines(); + logLines.Should().HaveCount(1); logLines[0].Should().Be("[WARNING] The resource graph is empty."); } @@ -339,7 +343,7 @@ public void Resolves_correct_type_for_lazy_loading_proxy() ResourceType resourceType = resourceGraph.GetResourceType(proxy.GetType()); // Assert - resourceType.ClrType.Should().Be(typeof(ResourceOfInt32)); + resourceType.ClrType.Should().Be(); } [Fact] diff --git a/test/JsonApiDotNetCoreTests/UnitTests/Serialization/Extensions/ResourceObjectConverterTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/Serialization/Extensions/ResourceObjectConverterTests.cs new file mode 100644 index 0000000000..2b0557bcdf --- /dev/null +++ b/test/JsonApiDotNetCoreTests/UnitTests/Serialization/Extensions/ResourceObjectConverterTests.cs @@ -0,0 +1,578 @@ +using System.Net; +using System.Text; +using System.Text.Json; +using FluentAssertions; +using JetBrains.Annotations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Errors; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; +using JsonApiDotNetCore.Serialization.JsonConverters; +using JsonApiDotNetCore.Serialization.Objects; +using Microsoft.Extensions.Logging.Abstractions; +using TestBuildingBlocks; +using Xunit; + +namespace JsonApiDotNetCoreTests.UnitTests.Serialization.Extensions; + +public sealed class ResourceObjectConverterTests +{ + private static readonly JsonApiMediaTypeExtension TypeInfoMediaTypeExtension = new("https://www.jsonapi.net/ext/type-info"); + + private static readonly JsonWriterOptions WriterOptions = new() + { + Indented = true + }; + + [Fact] + public void Permits_request_body_without_extension_usage() + { + // Arrange + TestContext testContext = TestContext.WithoutExtension; + + const string requestJson = """ + { + "type": "derivedTypes", + "attributes": { + "baseValue": "baseAttribute", + "derivedValue": "derivedAttribute" + }, + "relationships": { + "parent": { + "data": { + "type": "baseTypes", + "id": "1" + } + } + } + } + """; + + var reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(requestJson)); + + // Act + ResourceObject resourceObject = testContext.Converter.Read(ref reader, typeof(ResourceObject), testContext.SerializerReadOptions); + + // Assert + resourceObject.Attributes.Should().ContainKey("baseValue").WhoseValue.Should().Be("baseAttribute"); + resourceObject.Attributes.Should().ContainKey("derivedValue").WhoseValue.Should().Be("derivedAttribute"); + + resourceObject.Relationships.Should().ContainKey("parent").WhoseValue.With(value => + { + value.Should().NotBeNull(); + value.Data.SingleValue.Should().NotBeNull(); + value.Data.SingleValue.Type.Should().Be("baseTypes"); + value.Data.SingleValue.Id.Should().Be("1"); + }); + } + + [Fact] + public void Blocks_request_body_with_extension_in_attributes_when_extension_not_enabled() + { + // Arrange + TestContext testContext = TestContext.WithoutExtension; + + const string requestJson = """ + { + "type": "derivedTypes", + "attributes": { + "type-info:fail": false, + "baseValue": "baseAttribute", + "derivedValue": "derivedAttribute" + } + } + """; + + // Act + Action action = () => + { + var reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(requestJson)); + _ = testContext.Converter.Read(ref reader, typeof(ResourceObject), testContext.SerializerReadOptions); + }; + + // Assert + action.Should().ThrowExactly().WithMessage("Unsupported usage of JSON:API extension 'type-info' in attributes."); + } + + [Fact] + public void Blocks_request_body_with_extension_in_relationships_when_extension_not_enabled() + { + // Arrange + TestContext testContext = TestContext.WithoutExtension; + + const string requestJson = """ + { + "type": "derivedTypes", + "relationships": { + "type-info:fail": false, + "parent": { + "data": { + "type": "baseTypes", + "id": "1" + } + } + } + } + """; + + // Act + Action action = () => + { + var reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(requestJson)); + _ = testContext.Converter.Read(ref reader, typeof(ResourceObject), testContext.SerializerReadOptions); + }; + + // Assert + action.Should().ThrowExactly().WithMessage("Unsupported usage of JSON:API extension 'type-info' in relationships."); + } + + [Fact] + public void Permits_request_body_with_extension_when_extension_enabled() + { + // Arrange + TestContext testContext = TestContext.WithExtension; + + const string requestJson = """ + { + "type": "derivedTypes", + "attributes": { + "type-info:fail": false, + "baseValue": "baseAttribute", + "derivedValue": "derivedAttribute" + }, + "relationships": { + "type-info:fail": false, + "parent": { + "data": { + "type": "baseTypes", + "id": "1" + } + } + } + } + """; + + var reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(requestJson)); + + // Act + ResourceObject resourceObject = testContext.Converter.Read(ref reader, typeof(ResourceObject), testContext.SerializerReadOptions); + + // Assert + resourceObject.Attributes.Should().NotBeNull(); + resourceObject.Relationships.Should().NotBeNull(); + } + + [Fact] + public void Throws_for_request_body_with_extension_in_attributes_when_extension_enabled() + { + // Arrange + TestContext testContext = TestContext.WithExtension; + + const string requestJson = """ + { + "type": "derivedTypes", + "attributes": { + "type-info:fail": true, + "baseValue": "baseAttribute", + "derivedValue": "derivedAttribute" + } + } + """; + + // Act + Action action = () => + { + var reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(requestJson)); + _ = testContext.Converter.Read(ref reader, typeof(ResourceObject), testContext.SerializerReadOptions); + }; + + // Assert + JsonApiException? exception = action.Should().ThrowExactly().WithInnerExceptionExactly().Which; + + exception.StackTrace.Should().Contain(nameof(ExtensionAwareResourceObjectConverter)); + exception.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.BadRequest); + error.Title.Should().Be("Failure requested from attributes."); + error.Source.Should().NotBeNull(); + error.Source.Pointer.Should().Be("attributes/type-info:fail"); + } + + [Fact] + public void Throws_for_request_body_with_extension_in_relationships_when_extension_enabled() + { + // Arrange + TestContext testContext = TestContext.WithExtension; + + const string requestJson = """ + { + "type": "derivedTypes", + "relationships": { + "type-info:fail": true, + "parent": { + "data": { + "type": "baseTypes", + "id": "1" + } + } + } + } + """; + + // Act + Action action = () => + { + var reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(requestJson)); + _ = testContext.Converter.Read(ref reader, typeof(ResourceObject), testContext.SerializerReadOptions); + }; + + // Assert + JsonApiException? exception = action.Should().ThrowExactly().WithInnerExceptionExactly().Which; + + exception.StackTrace.Should().Contain(nameof(ExtensionAwareResourceObjectConverter)); + exception.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.BadRequest); + error.Title.Should().Be("Failure requested from relationships."); + error.Source.Should().NotBeNull(); + error.Source.Pointer.Should().Be("relationships/type-info:fail"); + } + + [Fact] + public void Hides_extension_in_response_body_when_extension_not_enabled() + { + // Arrange + TestContext testContext = TestContext.WithoutExtension; + + var resourceObject = new ResourceObject + { + Type = "derivedTypes", + Id = "1", + Attributes = new Dictionary + { + ["baseValue"] = "baseAttribute", + ["derivedValue"] = "derivedAttribute" + }, + Relationships = new Dictionary + { + ["parent"] = new() + { + Data = new SingleOrManyData(new ResourceIdentifierObject + { + Type = "baseTypes", + Id = "1" + }) + } + } + }; + + using var stream = new MemoryStream(); + + using (var writer = new Utf8JsonWriter(stream, WriterOptions)) + { + // Act + testContext.Converter.Write(writer, resourceObject, testContext.SerializerWriteOptions); + } + + // Assert + string responseJson = Encoding.UTF8.GetString(stream.ToArray()); + + responseJson.Should().BeJson(""" + { + "type": "derivedTypes", + "id": "1", + "attributes": { + "baseValue": "baseAttribute", + "derivedValue": "derivedAttribute" + }, + "relationships": { + "parent": { + "data": { + "type": "baseTypes", + "id": "1" + } + } + } + } + """); + } + + [Fact] + public void Hides_extension_in_response_body_when_extension_enabled_with_base_type() + { + // Arrange + TestContext testContext = TestContext.WithExtension; + + var resourceObject = new ResourceObject + { + Type = "baseTypes", + Id = "1", + Attributes = new Dictionary + { + ["baseValue"] = "baseAttribute" + }, + Relationships = new Dictionary + { + ["parent"] = new() + { + Data = new SingleOrManyData(new ResourceIdentifierObject + { + Type = "baseTypes", + Id = "1" + }) + } + } + }; + + using var stream = new MemoryStream(); + + using (var writer = new Utf8JsonWriter(stream, WriterOptions)) + { + // Act + testContext.Converter.Write(writer, resourceObject, testContext.SerializerWriteOptions); + } + + // Assert + string responseJson = Encoding.UTF8.GetString(stream.ToArray()); + + responseJson.Should().BeJson(""" + { + "type": "baseTypes", + "id": "1", + "attributes": { + "baseValue": "baseAttribute" + }, + "relationships": { + "parent": { + "data": { + "type": "baseTypes", + "id": "1" + } + } + } + } + """); + } + + [Fact] + public void Writes_extension_in_response_body_when_extension_enabled_with_derived_type() + { + // Arrange + TestContext testContext = TestContext.WithExtension; + + var resourceObject = new ResourceObject + { + Type = "derivedTypes", + Id = "1", + Attributes = new Dictionary + { + ["baseValue"] = "baseAttribute", + ["derivedValue"] = "derivedAttribute" + }, + Relationships = new Dictionary + { + ["parent"] = new() + { + Data = new SingleOrManyData(new ResourceIdentifierObject + { + Type = "baseTypes", + Id = "1" + }) + } + } + }; + + using var stream = new MemoryStream(); + + using (var writer = new Utf8JsonWriter(stream, WriterOptions)) + { + // Act + testContext.Converter.Write(writer, resourceObject, testContext.SerializerWriteOptions); + } + + // Assert + string responseJson = Encoding.UTF8.GetString(stream.ToArray()); + + responseJson.Should().BeJson(""" + { + "type": "derivedTypes", + "id": "1", + "attributes": { + "type-info:baseType": "baseTypes", + "baseValue": "baseAttribute", + "derivedValue": "derivedAttribute" + }, + "relationships": { + "type-info:baseType": "baseTypes", + "parent": { + "data": { + "type": "baseTypes", + "id": "1" + } + } + } + } + """); + } + + private sealed class ExtensionAwareResourceObjectConverter : ResourceObjectConverter + { + private const string ExtensionNamespace = "type-info"; + private const string ExtensionName = "fail"; + + private readonly IResourceGraph _resourceGraph; + private readonly JsonApiRequestAccessor _requestAccessor; + + private bool IsTypeInfoExtensionEnabled => _requestAccessor.Request.Extensions.Contains(TypeInfoMediaTypeExtension); + + public ExtensionAwareResourceObjectConverter(IResourceGraph resourceGraph, JsonApiRequestAccessor requestAccessor) + : base(resourceGraph) + { + ArgumentNullException.ThrowIfNull(resourceGraph); + ArgumentNullException.ThrowIfNull(requestAccessor); + + _resourceGraph = resourceGraph; + _requestAccessor = requestAccessor; + } + + private protected override void ValidateExtensionInAttributes(string extensionNamespace, string extensionName, ResourceType resourceType, + Utf8JsonReader reader) + { + if (extensionNamespace == ExtensionNamespace && IsTypeInfoExtensionEnabled && extensionName == ExtensionName) + { + if (reader.GetBoolean()) + { + CapturedThrow(new JsonApiException(new ErrorObject(HttpStatusCode.BadRequest) + { + Title = "Failure requested from attributes.", + Source = new ErrorSource + { + Pointer = $"attributes/{ExtensionNamespace}:{ExtensionName}" + } + })); + } + + return; + } + + base.ValidateExtensionInAttributes(extensionNamespace, extensionName, resourceType, reader); + } + + private protected override void ValidateExtensionInRelationships(string extensionNamespace, string extensionName, ResourceType resourceType, + Utf8JsonReader reader) + { + if (extensionNamespace == ExtensionNamespace && IsTypeInfoExtensionEnabled && extensionName == ExtensionName) + { + if (reader.GetBoolean()) + { + CapturedThrow(new JsonApiException(new ErrorObject(HttpStatusCode.BadRequest) + { + Title = "Failure requested from relationships.", + Source = new ErrorSource + { + Pointer = $"relationships/{ExtensionNamespace}:{ExtensionName}" + } + })); + } + + return; + } + + base.ValidateExtensionInRelationships(extensionNamespace, extensionName, resourceType, reader); + } + + private protected override void WriteExtensionInAttributes(Utf8JsonWriter writer, ResourceObject value) + { + WriteBaseType(writer, value); + } + + private protected override void WriteExtensionInRelationships(Utf8JsonWriter writer, ResourceObject value) + { + WriteBaseType(writer, value); + } + + private void WriteBaseType(Utf8JsonWriter writer, ResourceObject value) + { + if (IsTypeInfoExtensionEnabled && value.Type != null) + { + ResourceType? resourceType = _resourceGraph.FindResourceType(value.Type); + + if (resourceType is { BaseType: not null }) + { + writer.WriteString($"{ExtensionNamespace}:baseType", resourceType.BaseType.PublicName); + } + } + } + } + + private sealed class JsonApiRequestAccessor + { + public IJsonApiRequest Request { get; } + + public JsonApiRequestAccessor(IJsonApiRequest request) + { + ArgumentNullException.ThrowIfNull(request); + + Request = request; + } + } + + private sealed class TestContext + { + public static TestContext WithExtension { get; } = new(true); + public static TestContext WithoutExtension { get; } = new(false); + + public ExtensionAwareResourceObjectConverter Converter { get; } + public JsonSerializerOptions SerializerReadOptions { get; } + public JsonSerializerOptions SerializerWriteOptions { get; } + + private TestContext(bool includeExtension) + { + var options = new JsonApiOptions(); + var request = new JsonApiRequest(); + + if (includeExtension) + { + request.Extensions = new HashSet([TypeInfoMediaTypeExtension]); + } + + // @formatter:wrap_chained_method_calls chop_always + // @formatter:wrap_before_first_method_call true + + IResourceGraph resourceGraph = new ResourceGraphBuilder(options, NullLoggerFactory.Instance) + .Add() + .Add() + .Build(); + + // @formatter:wrap_before_first_method_call restore + // @formatter:wrap_chained_method_calls restore + + var requestAccessor = new JsonApiRequestAccessor(request); + Converter = new ExtensionAwareResourceObjectConverter(resourceGraph, requestAccessor); + + options.SerializerOptions.Converters.Add(Converter); + SerializerReadOptions = ((IJsonApiOptions)options).SerializerReadOptions; + SerializerWriteOptions = ((IJsonApiOptions)options).SerializerWriteOptions; + } + } + + [UsedImplicitly(ImplicitUseTargetFlags.Members)] + private class BaseType : Identifiable + { + [Attr] + public string? BaseValue { get; set; } + + [HasOne] + public BaseType? Parent { get; set; } + } + + [UsedImplicitly(ImplicitUseTargetFlags.Members)] + private sealed class DerivedType : BaseType + { + [Attr] + public string? DerivedValue { get; set; } + } +} diff --git a/test/JsonApiDotNetCoreTests/UnitTests/Serialization/Extensions/SourcePointerInExceptionTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/Serialization/Extensions/SourcePointerInExceptionTests.cs new file mode 100644 index 0000000000..1638c0b0d2 --- /dev/null +++ b/test/JsonApiDotNetCoreTests/UnitTests/Serialization/Extensions/SourcePointerInExceptionTests.cs @@ -0,0 +1,142 @@ +using System.Net; +using System.Text.Json; +using FluentAssertions; +using JetBrains.Annotations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Errors; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Serialization.JsonConverters; +using JsonApiDotNetCore.Serialization.Objects; +using JsonApiDotNetCore.Serialization.Request; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging.Abstractions; +using Xunit; + +namespace JsonApiDotNetCoreTests.UnitTests.Serialization.Extensions; + +public sealed class SourcePointerInExceptionTests +{ + private const string RequestBody = """ + { + "data": { + "type": "testResources", + "attributes": { + "ext-namespace:ext-name": "ignored" + } + } + } + """; + + [Fact] + public async Task Adds_source_pointer_to_JsonApiException_thrown_from_JsonConverter() + { + // Arrange + const string? relativeSourcePointer = null; + + var options = new JsonApiOptions(); + IResourceGraph resourceGraph = new ResourceGraphBuilder(options, NullLoggerFactory.Instance).Add().Build(); + var converter = new ThrowingResourceObjectConverter(resourceGraph, relativeSourcePointer); + var reader = new FakeJsonApiReader(RequestBody, options, converter); + var httpContext = new DefaultHttpContext(); + + // Act + Func action = async () => await reader.ReadAsync(httpContext.Request); + + // Assert + JsonApiException? exception = (await action.Should().ThrowExactlyAsync()).Which; + + exception.StackTrace.Should().Contain(nameof(ThrowingResourceObjectConverter)); + exception.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); + error.Title.Should().Be("Extension error"); + error.Source.Should().NotBeNull(); + error.Source.Pointer.Should().Be("/data"); + } + + [Fact] + public async Task Makes_source_pointer_absolute_in_JsonApiException_thrown_from_JsonConverter() + { + // Arrange + const string relativeSourcePointer = "relative/path"; + + var options = new JsonApiOptions(); + IResourceGraph resourceGraph = new ResourceGraphBuilder(options, NullLoggerFactory.Instance).Add().Build(); + var converter = new ThrowingResourceObjectConverter(resourceGraph, relativeSourcePointer); + var reader = new FakeJsonApiReader(RequestBody, options, converter); + var httpContext = new DefaultHttpContext(); + + // Act + Func action = async () => await reader.ReadAsync(httpContext.Request); + + // Assert + JsonApiException? exception = (await action.Should().ThrowExactlyAsync()).Which; + + exception.StackTrace.Should().Contain(nameof(ThrowingResourceObjectConverter)); + exception.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Errors[0]; + error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity); + error.Title.Should().Be("Extension error"); + error.Source.Should().NotBeNull(); + error.Source.Pointer.Should().Be("/data/relative/path"); + } + + [UsedImplicitly(ImplicitUseTargetFlags.Members)] + private sealed class TestResource : Identifiable; + + private sealed class ThrowingResourceObjectConverter(IResourceGraph resourceGraph, string? relativeSourcePointer) + : ResourceObjectConverter(resourceGraph) + { + private readonly string? _relativeSourcePointer = relativeSourcePointer; + + private protected override void ValidateExtensionInAttributes(string extensionNamespace, string extensionName, ResourceType resourceType, + Utf8JsonReader reader) + { + var exception = new JsonApiException(new ErrorObject(HttpStatusCode.UnprocessableEntity) + { + Title = "Extension error" + }); + + if (_relativeSourcePointer != null) + { + exception.Errors[0].Source = new ErrorSource + { + Pointer = _relativeSourcePointer + }; + } + + CapturedThrow(exception); + } + } + + private sealed class FakeJsonApiReader : IJsonApiReader + { + private readonly string _requestBody; + + private readonly JsonSerializerOptions _serializerOptions; + + public FakeJsonApiReader(string requestBody, JsonApiOptions options, ResourceObjectConverter converter) + { + _requestBody = requestBody; + + _serializerOptions = new JsonSerializerOptions(options.SerializerOptions); + _serializerOptions.Converters.Add(converter); + } + + public Task ReadAsync(HttpRequest httpRequest) + { + try + { + JsonSerializer.Deserialize(_requestBody, _serializerOptions); + } + catch (NotSupportedException exception) when (exception.HasJsonApiException()) + { + throw exception.EnrichSourcePointer(); + } + + return Task.FromResult(null); + } + } +} diff --git a/test/JsonApiDotNetCoreTests/UnitTests/Serialization/InputConversionTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/Serialization/InputConversionTests.cs index b16d29e28f..a7bc52ee4b 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/Serialization/InputConversionTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/Serialization/InputConversionTests.cs @@ -10,13 +10,14 @@ using JsonApiDotNetCore.Serialization.Objects; using JsonApiDotNetCore.Serialization.Request.Adapters; using Microsoft.Extensions.Logging.Abstractions; -using TestBuildingBlocks; using Xunit; namespace JsonApiDotNetCoreTests.UnitTests.Serialization; -public sealed class InputConversionTests +public sealed class InputConversionTests : IDisposable { + private readonly ServiceContainer _serviceProvider = new(); + [Fact] public void Converts_various_data_types_with_values() { @@ -56,8 +57,8 @@ public void Converts_various_data_types_with_values() Value = "Single" }; - var complexObjectList = new List - { + List complexObjectList = + [ new() { Value = "One" @@ -66,7 +67,7 @@ public void Converts_various_data_types_with_values() { Value = "Two" } - }; + ]; var document = new Document { @@ -107,7 +108,7 @@ public void Converts_various_data_types_with_values() var model = (ResourceWithVariousDataTypes?)documentAdapter.Convert(document); // Assert - model.ShouldNotBeNull(); + model.Should().NotBeNull(); model.Boolean.Should().Be(booleanValue); model.NullableBoolean.Should().Be(nullableBooleanValue); @@ -132,10 +133,10 @@ public void Converts_various_data_types_with_values() model.Enum.Should().Be(enumValue); model.NullableEnum.Should().Be(nullableEnumValue); - model.ComplexObject.ShouldNotBeNull(); + model.ComplexObject.Should().NotBeNull(); model.ComplexObject.Value.Should().Be(complexObject.Value); - model.ComplexObjectList.ShouldHaveCount(2); + model.ComplexObjectList.Should().HaveCount(2); model.ComplexObjectList[0].Value.Should().Be(complexObjectList[0].Value); model.ComplexObjectList[1].Value.Should().Be(complexObjectList[1].Value); } @@ -151,26 +152,26 @@ public void Converts_various_data_types_with_defaults() WriteOperation = WriteOperationKind.CreateResource }); - const bool booleanValue = default; - const bool nullableBooleanValue = default; - const char charValue = default; - const char nullableCharValue = default; - const ulong unsignedLongValue = default; - const ulong nullableUnsignedLongValue = default; - const decimal decimalValue = default; - const decimal nullableDecimalValue = default; - const float floatValue = default; - const float nullableFloatValue = default; - const string stringValue = default!; - const string? nullableStringValue = default; - Guid guidValue = default; - Guid nullableGuidValue = default; + const bool booleanValue = false; + const bool nullableBooleanValue = false; + const char charValue = '\0'; + const char nullableCharValue = '\0'; + const ulong unsignedLongValue = 0; + const ulong nullableUnsignedLongValue = 0; + const decimal decimalValue = 0; + const decimal nullableDecimalValue = 0; + const float floatValue = 0; + const float nullableFloatValue = 0; + const string stringValue = null!; + const string? nullableStringValue = null; + var guidValue = Guid.Empty; + var nullableGuidValue = Guid.Empty; DateTime dateTimeValue = default; DateTime nullableDateTimeValue = default; DateTimeOffset dateTimeOffsetValue = default; DateTimeOffset nullableDateTimeOffsetValue = default; - TimeSpan timeSpanValue = default; - TimeSpan nullableTimeSpanValue = default; + TimeSpan timeSpanValue = TimeSpan.Zero; + TimeSpan nullableTimeSpanValue = TimeSpan.Zero; const DayOfWeek enumValue = default; const DayOfWeek nullableEnumValue = default; @@ -213,7 +214,7 @@ public void Converts_various_data_types_with_defaults() var model = (ResourceWithVariousDataTypes?)documentAdapter.Convert(document); // Assert - model.ShouldNotBeNull(); + model.Should().NotBeNull(); model.Boolean.Should().Be(booleanValue); model.NullableBoolean.Should().Be(nullableBooleanValue); @@ -241,19 +242,18 @@ public void Converts_various_data_types_with_defaults() model.ComplexObjectList.Should().BeNull(); } - private static DocumentAdapter CreateDocumentAdapter(Func createRequest) + private DocumentAdapter CreateDocumentAdapter(Func createRequest) where TResource : Identifiable { var options = new JsonApiOptions(); IResourceGraph resourceGraph = new ResourceGraphBuilder(options, NullLoggerFactory.Instance).Add().Build(); options.SerializerOptions.Converters.Add(new ResourceObjectConverter(resourceGraph)); - var serviceContainer = new ServiceContainer(); - var resourceFactory = new ResourceFactory(serviceContainer); - var resourceDefinitionAccessor = new ResourceDefinitionAccessor(resourceGraph, serviceContainer); + var resourceFactory = new ResourceFactory(_serviceProvider); + var resourceDefinitionAccessor = new ResourceDefinitionAccessor(resourceGraph, _serviceProvider); - serviceContainer.AddService(typeof(IResourceDefinitionAccessor), resourceDefinitionAccessor); - serviceContainer.AddService(typeof(IResourceDefinition), new JsonApiResourceDefinition(resourceGraph)); + _serviceProvider.AddService(typeof(IResourceDefinitionAccessor), resourceDefinitionAccessor); + _serviceProvider.AddService(typeof(IResourceDefinition), new JsonApiResourceDefinition(resourceGraph)); JsonApiRequest request = createRequest(resourceGraph); var targetedFields = new TargetedFields(); @@ -275,6 +275,11 @@ private static DocumentAdapter CreateDocumentAdapter(Func { diff --git a/test/JsonApiDotNetCoreTests/UnitTests/Serialization/Response/ResponseModelAdapterTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/Serialization/Response/ResponseModelAdapterTests.cs index 2d2e07e600..89de6ba3e8 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/Serialization/Response/ResponseModelAdapterTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/Serialization/Response/ResponseModelAdapterTests.cs @@ -22,13 +22,13 @@ public void Resources_in_deeply_nested_circular_chain_are_written_in_relationshi // Arrange var fakers = new ResponseSerializationFakers(); - Article article = fakers.Article.Generate(); - article.Author = fakers.Person.Generate(); - article.Author.Blogs = fakers.Blog.Generate(2).ToHashSet(); + Article article = fakers.Article.GenerateOne(); + article.Author = fakers.Person.GenerateOne(); + article.Author.Blogs = fakers.Blog.GenerateSet(2); article.Author.Blogs.ElementAt(0).Reviewer = article.Author; - article.Author.Blogs.ElementAt(1).Reviewer = fakers.Person.Generate(); - article.Author.FavoriteFood = fakers.Food.Generate(); - article.Author.Blogs.ElementAt(1).Reviewer.FavoriteFood = fakers.Food.Generate(); + article.Author.Blogs.ElementAt(1).Reviewer = fakers.Person.GenerateOne(); + article.Author.FavoriteFood = fakers.Food.GenerateOne(); + article.Author.Blogs.ElementAt(1).Reviewer.FavoriteFood = fakers.Food.GenerateOne(); IJsonApiOptions options = new JsonApiOptions { @@ -163,15 +163,15 @@ public void Resources_in_deeply_nested_circular_chains_are_written_in_relationsh // Arrange var fakers = new ResponseSerializationFakers(); - Article article1 = fakers.Article.Generate(); - article1.Author = fakers.Person.Generate(); - article1.Author.Blogs = fakers.Blog.Generate(2).ToHashSet(); + Article article1 = fakers.Article.GenerateOne(); + article1.Author = fakers.Person.GenerateOne(); + article1.Author.Blogs = fakers.Blog.GenerateSet(2); article1.Author.Blogs.ElementAt(0).Reviewer = article1.Author; - article1.Author.Blogs.ElementAt(1).Reviewer = fakers.Person.Generate(); - article1.Author.FavoriteFood = fakers.Food.Generate(); - article1.Author.Blogs.ElementAt(1).Reviewer.FavoriteFood = fakers.Food.Generate(); + article1.Author.Blogs.ElementAt(1).Reviewer = fakers.Person.GenerateOne(); + article1.Author.FavoriteFood = fakers.Food.GenerateOne(); + article1.Author.Blogs.ElementAt(1).Reviewer.FavoriteFood = fakers.Food.GenerateOne(); - Article article2 = fakers.Article.Generate(); + Article article2 = fakers.Article.GenerateOne(); article2.Author = article1.Author; IJsonApiOptions options = new JsonApiOptions @@ -328,22 +328,22 @@ public void Resources_in_overlapping_deeply_nested_circular_chains_are_written_i // Arrange var fakers = new ResponseSerializationFakers(); - Article article = fakers.Article.Generate(); - article.Author = fakers.Person.Generate(); - article.Author.Blogs = fakers.Blog.Generate(2).ToHashSet(); + Article article = fakers.Article.GenerateOne(); + article.Author = fakers.Person.GenerateOne(); + article.Author.Blogs = fakers.Blog.GenerateSet(2); article.Author.Blogs.ElementAt(0).Reviewer = article.Author; - article.Author.Blogs.ElementAt(1).Reviewer = fakers.Person.Generate(); - article.Author.FavoriteFood = fakers.Food.Generate(); - article.Author.Blogs.ElementAt(1).Reviewer.FavoriteFood = fakers.Food.Generate(); + article.Author.Blogs.ElementAt(1).Reviewer = fakers.Person.GenerateOne(); + article.Author.FavoriteFood = fakers.Food.GenerateOne(); + article.Author.Blogs.ElementAt(1).Reviewer.FavoriteFood = fakers.Food.GenerateOne(); - article.Reviewer = fakers.Person.Generate(); - article.Reviewer.Blogs = fakers.Blog.Generate(1).ToHashSet(); + article.Reviewer = fakers.Person.GenerateOne(); + article.Reviewer.Blogs = fakers.Blog.GenerateSet(1); article.Reviewer.Blogs.Add(article.Author.Blogs.ElementAt(0)); article.Reviewer.Blogs.ElementAt(0).Author = article.Reviewer; article.Reviewer.Blogs.ElementAt(1).Author = article.Author.Blogs.ElementAt(1).Reviewer; - article.Author.Blogs.ElementAt(1).Reviewer.FavoriteSong = fakers.Song.Generate(); - article.Reviewer.FavoriteSong = fakers.Song.Generate(); + article.Author.Blogs.ElementAt(1).Reviewer.FavoriteSong = fakers.Song.GenerateOne(); + article.Reviewer.FavoriteSong = fakers.Song.GenerateOne(); IJsonApiOptions options = new JsonApiOptions { @@ -553,8 +553,8 @@ public void Duplicate_children_in_multiple_chains_occur_once_in_output() // Arrange var fakers = new ResponseSerializationFakers(); - Person person = fakers.Person.Generate(); - List
articles = fakers.Article.Generate(5); + Person person = fakers.Person.GenerateOne(); + List
articles = fakers.Article.GenerateList(5); articles.ForEach(article => article.Author = person); articles.ForEach(article => article.Reviewer = person); @@ -565,9 +565,9 @@ public void Duplicate_children_in_multiple_chains_occur_once_in_output() Document document = responseModelAdapter.Convert(articles); // Assert - document.Included.ShouldHaveCount(1); + document.Included.Should().HaveCount(1); - document.Included[0].Attributes.ShouldContainKey("name").With(value => value.Should().Be(person.Name)); + document.Included[0].Attributes.Should().ContainKey("name").WhoseValue.Should().Be(person.Name); document.Included[0].Id.Should().Be(person.StringId); } diff --git a/test/JsonApiDotNetCoreTests/UnitTests/TypeConversion/RuntimeTypeConverterTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/TypeConversion/RuntimeTypeConverterTests.cs index 1263912faf..c7b0bf9450 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/TypeConversion/RuntimeTypeConverterTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/TypeConversion/RuntimeTypeConverterTests.cs @@ -109,29 +109,29 @@ public void Returns_same_instance_for_interface() } [Theory] - [InlineData(typeof(bool), default(bool))] + [InlineData(typeof(bool), false)] [InlineData(typeof(bool?), null)] - [InlineData(typeof(byte), default(byte))] + [InlineData(typeof(byte), 0)] [InlineData(typeof(byte?), null)] - [InlineData(typeof(sbyte), default(sbyte))] + [InlineData(typeof(sbyte), 0)] [InlineData(typeof(sbyte?), null)] - [InlineData(typeof(char), default(char))] + [InlineData(typeof(char), '\0')] [InlineData(typeof(char?), null)] - [InlineData(typeof(short), default(short))] + [InlineData(typeof(short), 0)] [InlineData(typeof(short?), null)] - [InlineData(typeof(ushort), default(ushort))] + [InlineData(typeof(ushort), 0)] [InlineData(typeof(ushort?), null)] - [InlineData(typeof(int), default(int))] + [InlineData(typeof(int), 0)] [InlineData(typeof(int?), null)] - [InlineData(typeof(uint), default(uint))] + [InlineData(typeof(uint), 0)] [InlineData(typeof(uint?), null)] - [InlineData(typeof(long), default(long))] + [InlineData(typeof(long), 0)] [InlineData(typeof(long?), null)] - [InlineData(typeof(ulong), default(ulong))] + [InlineData(typeof(ulong), 0)] [InlineData(typeof(ulong?), null)] - [InlineData(typeof(float), default(float))] + [InlineData(typeof(float), 0)] [InlineData(typeof(float?), null)] - [InlineData(typeof(double), default(double))] + [InlineData(typeof(double), 0)] [InlineData(typeof(double?), null)] [InlineData(typeof(decimal), 0)] [InlineData(typeof(decimal?), null)] diff --git a/test/MultiDbContextTests/MultiDbContextTests.csproj b/test/MultiDbContextTests/MultiDbContextTests.csproj index 54497bfada..e80f03c69e 100644 --- a/test/MultiDbContextTests/MultiDbContextTests.csproj +++ b/test/MultiDbContextTests/MultiDbContextTests.csproj @@ -1,6 +1,6 @@ - net8.0;net6.0 + net9.0;net8.0 diff --git a/test/MultiDbContextTests/ResourceTests.cs b/test/MultiDbContextTests/ResourceTests.cs index 3b2c259c57..a648f75cfc 100644 --- a/test/MultiDbContextTests/ResourceTests.cs +++ b/test/MultiDbContextTests/ResourceTests.cs @@ -35,8 +35,8 @@ public async Task Can_get_ResourceAs() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("nameA").With(value => value.Should().Be("SampleA")); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("nameA").WhoseValue.Should().Be("SampleA"); } [Fact] @@ -51,8 +51,8 @@ public async Task Can_get_ResourceBs() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("nameB").With(value => value.Should().Be("SampleB")); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("nameB").WhoseValue.Should().Be("SampleB"); } protected override HttpClient CreateClient() diff --git a/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj b/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj index 080666d491..4deb6b21cd 100644 --- a/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj +++ b/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj @@ -1,6 +1,6 @@ - net8.0;net6.0 + net9.0;net8.0 diff --git a/test/NoEntityFrameworkTests/NullSafeExpressionRewriterTests.cs b/test/NoEntityFrameworkTests/NullSafeExpressionRewriterTests.cs index 0a61821987..23250ddb1c 100644 --- a/test/NoEntityFrameworkTests/NullSafeExpressionRewriterTests.cs +++ b/test/NoEntityFrameworkTests/NullSafeExpressionRewriterTests.cs @@ -18,8 +18,8 @@ public void Can_rewrite_where_clause_with_constant_comparison() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { + List dataSource = + [ new() { Id = generator.GetNext() @@ -32,7 +32,7 @@ public void Can_rewrite_where_clause_with_constant_comparison() Id = generator.GetNext() } } - }; + ]; TestResource lastInDataSource = dataSource.Last(); @@ -57,8 +57,8 @@ public void Can_rewrite_where_clause_with_member_comparison() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { + List dataSource = + [ new() { Id = generator.GetNext() @@ -102,7 +102,7 @@ public void Can_rewrite_where_clause_with_member_comparison() } } } - }; + ]; TestResource lastInDataSource = dataSource.Last(); lastInDataSource.FirstChild!.Parent!.Id = lastInDataSource.Parent!.Id; @@ -130,8 +130,8 @@ public void Can_rewrite_where_clause_with_not_comparison() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { + List dataSource = + [ new() { Id = generator.GetNext() @@ -144,7 +144,7 @@ public void Can_rewrite_where_clause_with_not_comparison() Id = generator.GetNext() } } - }; + ]; // ReSharper disable once NegativeEqualityExpression Expression, IEnumerable>> expression = source => source.Where(resource => !(resource.Parent!.Id == 3)); @@ -168,8 +168,8 @@ public void Can_rewrite_where_clause_with_any_comparison() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { + List dataSource = + [ new() { Id = generator.GetNext() @@ -201,7 +201,7 @@ public void Can_rewrite_where_clause_with_any_comparison() } } } - }; + ]; TestResource lastInDataSource = dataSource.Last(); @@ -228,8 +228,8 @@ public void Can_rewrite_where_clause_with_conditional_any_comparison() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { + List dataSource = + [ new() { Id = generator.GetNext() @@ -260,7 +260,7 @@ public void Can_rewrite_where_clause_with_conditional_any_comparison() } } } - }; + ]; // ReSharper disable once NegativeEqualityExpression Expression, IEnumerable>> expression = source => source.Where(resource => @@ -287,8 +287,8 @@ public void Can_rewrite_where_clause_with_nested_conditional_any_comparison() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { + List dataSource = + [ new() { Id = generator.GetNext(), @@ -335,7 +335,7 @@ public void Can_rewrite_where_clause_with_nested_conditional_any_comparison() } } } - }; + ]; TestResource lastInDataSource = dataSource.Last(); @@ -363,8 +363,8 @@ public void Can_rewrite_where_clause_with_count_comparison() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { + List dataSource = + [ new() { Id = generator.GetNext() @@ -404,14 +404,16 @@ public void Can_rewrite_where_clause_with_count_comparison() } } } - }; + ]; TestResource lastInDataSource = dataSource.Last(); +#pragma warning disable CA1829 // Use Length/Count property instead of Count() when available // ReSharper disable UseCollectionCountProperty Expression, IEnumerable>> expression = source => source.Where(resource => resource.Children.Count() > resource.Parent!.Children.Count()); // ReSharper restore UseCollectionCountProperty +#pragma warning restore CA1829 // Use Length/Count property instead of Count() when available var rewriter = new NullSafeExpressionRewriter(); @@ -433,8 +435,8 @@ public void Can_rewrite_order_by_clause_with_long() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { + List dataSource = + [ new() { Id = generator.GetNext() @@ -455,7 +457,7 @@ public void Can_rewrite_order_by_clause_with_long() Id = generator.GetNext() } } - }; + ]; Expression, IEnumerable>> expression = source => source.OrderBy(resource => resource.Parent!.Id); @@ -480,8 +482,8 @@ public void Can_rewrite_order_by_clause_with_IntPtr() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { + List dataSource = + [ new() { Id = generator.GetNext() @@ -503,7 +505,7 @@ public void Can_rewrite_order_by_clause_with_IntPtr() Pointer = OnePointer } } - }; + ]; Expression, IEnumerable>> expression = source => source.OrderBy(resource => resource.Parent!.Pointer); @@ -529,8 +531,8 @@ public void Can_rewrite_order_by_clause_with_nullable_int() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { + List dataSource = + [ new() { Id = generator.GetNext() @@ -552,7 +554,7 @@ public void Can_rewrite_order_by_clause_with_nullable_int() Number = -1 } } - }; + ]; Expression, IEnumerable>> expression = source => source.OrderBy(resource => resource.Parent!.Number); @@ -577,8 +579,8 @@ public void Can_rewrite_order_by_clause_with_enum() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { + List dataSource = + [ new() { Id = generator.GetNext() @@ -600,7 +602,7 @@ public void Can_rewrite_order_by_clause_with_enum() Enum = TestEnum.Two } } - }; + ]; Expression, IEnumerable>> expression = source => source.OrderBy(resource => resource.Parent!.Enum); @@ -625,8 +627,8 @@ public void Can_rewrite_order_by_clause_with_string() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { + List dataSource = + [ new() { Id = generator.GetNext() @@ -648,7 +650,7 @@ public void Can_rewrite_order_by_clause_with_string() Name = "X" } } - }; + ]; Expression, IEnumerable>> expression = source => source.OrderBy(resource => resource.Parent!.Name); @@ -673,8 +675,8 @@ public void Can_rewrite_order_by_clause_with_count() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { + List dataSource = + [ new() { Id = generator.GetNext() @@ -711,11 +713,13 @@ public void Can_rewrite_order_by_clause_with_count() } } } - }; + ]; +#pragma warning disable CA1829 // Use Length/Count property instead of Count() when available // ReSharper disable once UseCollectionCountProperty Expression, IEnumerable>> expression = source => source.OrderBy(resource => resource.Parent!.Children.Count()); +#pragma warning restore CA1829 // Use Length/Count property instead of Count() when available var rewriter = new NullSafeExpressionRewriter(); @@ -740,8 +744,8 @@ public void Can_rewrite_nested_descending_order_by_clauses() // Arrange var generator = new IdGenerator(); - var dataSource = new List - { + List dataSource = + [ new() { Id = generator.GetNext() @@ -786,7 +790,7 @@ public void Can_rewrite_nested_descending_order_by_clauses() Number = 10 } } - }; + ]; Expression, IEnumerable>> expression = source => source.OrderByDescending(resource => resource.Parent!.Name).ThenByDescending(resource => resource.Parent!.Number); diff --git a/test/NoEntityFrameworkTests/PersonTests.cs b/test/NoEntityFrameworkTests/PersonTests.cs index 01cdefa3e5..c450239429 100644 --- a/test/NoEntityFrameworkTests/PersonTests.cs +++ b/test/NoEntityFrameworkTests/PersonTests.cs @@ -35,7 +35,7 @@ public async Task Can_get_primary_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Meta.Should().ContainTotal(2); } @@ -52,8 +52,8 @@ public async Task Can_filter_in_primary_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("firstName").With(value => value.Should().Be("Jane")); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("firstName").WhoseValue.Should().Be("Jane"); responseDocument.Meta.Should().ContainTotal(1); } @@ -70,8 +70,8 @@ public async Task Can_filter_in_related_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("firstName").With(value => value.Should().Be("John")); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("firstName").WhoseValue.Should().Be("John"); responseDocument.Meta.Should().ContainTotal(1); } @@ -88,7 +88,7 @@ public async Task Can_sort_on_attribute_in_primary_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue[0].Id.Should().Be("2"); responseDocument.Data.ManyValue[1].Id.Should().Be("1"); } @@ -105,7 +105,7 @@ public async Task Can_sort_on_count_in_primary_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); + responseDocument.Data.ManyValue.Should().HaveCount(2); responseDocument.Data.ManyValue[0].Id.Should().Be("1"); responseDocument.Data.ManyValue[1].Id.Should().Be("2"); } @@ -122,8 +122,8 @@ public async Task Can_paginate_in_primary_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("firstName").With(value => value.Should().Be("Jane")); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("firstName").WhoseValue.Should().Be("Jane"); responseDocument.Meta.Should().ContainTotal(2); } @@ -140,8 +140,8 @@ public async Task Can_select_fields_in_primary_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldNotBeEmpty(); - responseDocument.Data.ManyValue.Should().AllSatisfy(resource => resource.Attributes.ShouldOnlyContainKeys("lastName", "displayName")); + responseDocument.Data.ManyValue.Should().NotBeEmpty(); + responseDocument.Data.ManyValue.Should().AllSatisfy(resource => resource.Attributes.Should().OnlyContainKeys("lastName", "displayName")); } [Fact] @@ -172,7 +172,7 @@ public async Task Can_get_primary_resource() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be("1"); } @@ -188,9 +188,9 @@ public async Task Can_get_secondary_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("description").With(value => value.Should().Be("Make homework")); - responseDocument.Data.ManyValue[1].Attributes.ShouldContainKey("description").With(value => value.Should().Be("Check emails")); + responseDocument.Data.ManyValue.Should().HaveCount(2); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("description").WhoseValue.Should().Be("Make homework"); + responseDocument.Data.ManyValue[1].Attributes.Should().ContainKey("description").WhoseValue.Should().Be("Check emails"); responseDocument.Meta.Should().ContainTotal(2); } @@ -207,7 +207,7 @@ public async Task Can_get_ToMany_relationship() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be("1"); responseDocument.Meta.Should().ContainTotal(1); diff --git a/test/NoEntityFrameworkTests/TagTests.cs b/test/NoEntityFrameworkTests/TagTests.cs index 49b5887adb..9bcb719771 100644 --- a/test/NoEntityFrameworkTests/TagTests.cs +++ b/test/NoEntityFrameworkTests/TagTests.cs @@ -35,7 +35,7 @@ public async Task Can_get_primary_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(3); + responseDocument.Data.ManyValue.Should().HaveCount(3); responseDocument.Meta.Should().ContainTotal(3); } @@ -52,8 +52,8 @@ public async Task Can_filter_in_primary_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("name").With(value => value.Should().Be("Personal")); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("name").WhoseValue.Should().Be("Personal"); responseDocument.Meta.Should().ContainTotal(1); } @@ -70,8 +70,8 @@ public async Task Can_filter_in_related_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("name").With(value => value.Should().Be("Business")); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("name").WhoseValue.Should().Be("Business"); responseDocument.Meta.Should().ContainTotal(1); } @@ -88,7 +88,7 @@ public async Task Can_sort_on_attribute_in_primary_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(3); + responseDocument.Data.ManyValue.Should().HaveCount(3); responseDocument.Data.ManyValue[0].Id.Should().Be("3"); responseDocument.Data.ManyValue[1].Id.Should().Be("2"); responseDocument.Data.ManyValue[2].Id.Should().Be("1"); @@ -106,7 +106,7 @@ public async Task Can_sort_on_count_in_primary_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(3); + responseDocument.Data.ManyValue.Should().HaveCount(3); responseDocument.Data.ManyValue[0].Id.Should().Be("1"); responseDocument.Data.ManyValue[1].Id.Should().Be("2"); responseDocument.Data.ManyValue[2].Id.Should().Be("3"); @@ -124,8 +124,8 @@ public async Task Can_paginate_in_primary_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("name").With(value => value.Should().Be("Family")); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("name").WhoseValue.Should().Be("Family"); responseDocument.Meta.Should().ContainTotal(3); } @@ -142,9 +142,9 @@ public async Task Can_select_fields_in_primary_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldNotBeEmpty(); + responseDocument.Data.ManyValue.Should().NotBeEmpty(); responseDocument.Data.ManyValue.Should().AllSatisfy(resource => resource.Attributes.Should().BeNull()); - responseDocument.Data.ManyValue.Should().AllSatisfy(resource => resource.Relationships.ShouldOnlyContainKeys("todoItems")); + responseDocument.Data.ManyValue.Should().AllSatisfy(resource => resource.Relationships.Should().OnlyContainKeys("todoItems")); } [Fact] @@ -175,7 +175,7 @@ public async Task Can_get_primary_resource() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be("1"); } @@ -191,10 +191,10 @@ public async Task Can_get_secondary_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(3); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("description").With(value => value.Should().Be("Make homework")); - responseDocument.Data.ManyValue[1].Attributes.ShouldContainKey("description").With(value => value.Should().Be("Book vacation")); - responseDocument.Data.ManyValue[2].Attributes.ShouldContainKey("description").With(value => value.Should().Be("Cook dinner")); + responseDocument.Data.ManyValue.Should().HaveCount(3); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("description").WhoseValue.Should().Be("Make homework"); + responseDocument.Data.ManyValue[1].Attributes.Should().ContainKey("description").WhoseValue.Should().Be("Book vacation"); + responseDocument.Data.ManyValue[2].Attributes.Should().ContainKey("description").WhoseValue.Should().Be("Cook dinner"); responseDocument.Meta.Should().ContainTotal(3); } @@ -211,7 +211,7 @@ public async Task Can_get_ToMany_relationship() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be("3"); responseDocument.Meta.Should().ContainTotal(1); diff --git a/test/NoEntityFrameworkTests/TodoItemTests.cs b/test/NoEntityFrameworkTests/TodoItemTests.cs index 90691fd770..1e691c9cd8 100644 --- a/test/NoEntityFrameworkTests/TodoItemTests.cs +++ b/test/NoEntityFrameworkTests/TodoItemTests.cs @@ -35,7 +35,7 @@ public async Task Can_get_primary_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(4); + responseDocument.Data.ManyValue.Should().HaveCount(4); responseDocument.Meta.Should().ContainTotal(4); } @@ -52,8 +52,8 @@ public async Task Can_filter_in_primary_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("priority").With(value => value.Should().Be(TodoItemPriority.High)); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("priority").WhoseValue.Should().Be(TodoItemPriority.High); responseDocument.Meta.Should().ContainTotal(1); } @@ -70,7 +70,7 @@ public async Task Can_filter_in_related_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(3); + responseDocument.Data.ManyValue.Should().HaveCount(3); responseDocument.Meta.Should().ContainTotal(3); } @@ -87,7 +87,7 @@ public async Task Can_sort_on_attribute_in_primary_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(4); + responseDocument.Data.ManyValue.Should().HaveCount(4); responseDocument.Data.ManyValue[0].Id.Should().Be("4"); responseDocument.Data.ManyValue[1].Id.Should().Be("3"); responseDocument.Data.ManyValue[2].Id.Should().Be("2"); @@ -106,7 +106,7 @@ public async Task Can_sort_on_count_in_primary_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(4); + responseDocument.Data.ManyValue.Should().HaveCount(4); responseDocument.Data.ManyValue[0].Id.Should().Be("2"); } @@ -122,8 +122,8 @@ public async Task Can_paginate_in_primary_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("description").With(value => value.Should().Be("Check emails")); + responseDocument.Data.ManyValue.Should().HaveCount(1); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("description").WhoseValue.Should().Be("Check emails"); responseDocument.Meta.Should().ContainTotal(4); } @@ -140,8 +140,8 @@ public async Task Can_select_fields_in_primary_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldNotBeEmpty(); - responseDocument.Data.ManyValue.Should().AllSatisfy(resource => resource.Attributes.ShouldOnlyContainKeys("description", "priority")); + responseDocument.Data.ManyValue.Should().NotBeEmpty(); + responseDocument.Data.ManyValue.Should().AllSatisfy(resource => resource.Attributes.Should().OnlyContainKeys("description", "priority")); } [Fact] @@ -172,7 +172,7 @@ public async Task Can_get_primary_resource() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Id.Should().Be("1"); } @@ -188,7 +188,7 @@ public async Task Cannot_get_primary_resource_for_unknown_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -208,9 +208,9 @@ public async Task Can_get_secondary_resources() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(2); - responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("name").With(value => value.Should().Be("Personal")); - responseDocument.Data.ManyValue[1].Attributes.ShouldContainKey("name").With(value => value.Should().Be("Family")); + responseDocument.Data.ManyValue.Should().HaveCount(2); + responseDocument.Data.ManyValue[0].Attributes.Should().ContainKey("name").WhoseValue.Should().Be("Personal"); + responseDocument.Data.ManyValue[1].Attributes.Should().ContainKey("name").WhoseValue.Should().Be("Family"); responseDocument.Meta.Should().ContainTotal(2); } @@ -227,9 +227,9 @@ public async Task Can_get_secondary_resource() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("people"); - responseDocument.Data.SingleValue.Attributes.ShouldContainKey("firstName").With(value => value.Should().Be("Jane")); + responseDocument.Data.SingleValue.Attributes.Should().ContainKey("firstName").WhoseValue.Should().Be("Jane"); } [Fact] @@ -244,7 +244,7 @@ public async Task Cannot_get_secondary_resource_for_unknown_primary_ID() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -279,7 +279,7 @@ public async Task Cannot_get_secondary_resource_for_unknown_relationship() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.NotFound); - responseDocument.Errors.ShouldHaveCount(1); + responseDocument.Errors.Should().HaveCount(1); ErrorObject error = responseDocument.Errors[0]; error.StatusCode.Should().Be(HttpStatusCode.NotFound); @@ -299,7 +299,7 @@ public async Task Can_get_ToOne_relationship() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.SingleValue.ShouldNotBeNull(); + responseDocument.Data.SingleValue.Should().NotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("people"); responseDocument.Data.SingleValue.Id.Should().Be("2"); } @@ -331,7 +331,7 @@ public async Task Can_get_ToMany_relationship() // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - responseDocument.Data.ManyValue.ShouldHaveCount(1); + responseDocument.Data.ManyValue.Should().HaveCount(1); responseDocument.Data.ManyValue[0].Id.Should().Be("3"); responseDocument.Meta.Should().ContainTotal(1); diff --git a/test/OpenApiKiotaEndToEndTests/AdditionalPropertiesTests.cs b/test/OpenApiKiotaEndToEndTests/AdditionalPropertiesTests.cs new file mode 100644 index 0000000000..d3f8d75d43 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AdditionalPropertiesTests.cs @@ -0,0 +1,32 @@ +using System.Reflection; +using FluentAssertions; +using Xunit; + +namespace OpenApiKiotaEndToEndTests; + +public sealed class AdditionalPropertiesTests +{ + private static readonly string GeneratedCodeDirectory = $"{Path.DirectorySeparatorChar}GeneratedCode{Path.DirectorySeparatorChar}"; + + [Fact] + public async Task Additional_properties_are_only_allowed_in_meta() + { + string startDirectory = Path.GetFullPath(Path.Combine(Assembly.GetExecutingAssembly().Location, "../../../../")); + + foreach (string path in Directory.EnumerateFiles(startDirectory, "*.cs", new EnumerationOptions + { + MatchType = MatchType.Simple, + RecurseSubdirectories = true + })) + { + if (path.Contains(GeneratedCodeDirectory, StringComparison.OrdinalIgnoreCase) && + !string.Equals(Path.GetFileName(path), "Meta.cs", StringComparison.OrdinalIgnoreCase)) + { + string content = await File.ReadAllTextAsync(path); + bool containsAdditionalData = content.Contains("public IDictionary AdditionalData"); + + containsAdditionalData.Should().BeFalse($"file '{path}' should not contain AdditionalData"); + } + } + } +} diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicCreateResourceTests.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicCreateResourceTests.cs new file mode 100644 index 0000000000..0af2eff72c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicCreateResourceTests.cs @@ -0,0 +1,214 @@ +using FluentAssertions; +using Microsoft.Kiota.Abstractions; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode; +using OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.AtomicOperations; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.AtomicOperations; + +public sealed class AtomicCreateResourceTests : IClassFixture, OperationsDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, OperationsDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly OperationsFakers _fakers; + + public AtomicCreateResourceTests(IntegrationTestContext, OperationsDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseController(); + + _fakers = new OperationsFakers(testContext.Factory.Services); + } + + [Fact] + public async Task Can_create_resource_with_attributes() + { + // Arrange + Teacher newTeacher = _fakers.Teacher.GenerateOne(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new AtomicOperationsClient(requestAdapter); + + OperationsRequestDocument requestBody = new() + { + AtomicOperations = + [ + new CreateTeacherOperation + { + Op = AddOperationCode.Add, + Data = new DataInCreateTeacherRequest + { + Type = ResourceType.Teachers, + Attributes = new AttributesInCreateTeacherRequest + { + Name = newTeacher.Name, + EmailAddress = newTeacher.EmailAddress + } + } + } + ] + }; + + // Act + OperationsResponseDocument? response = await apiClient.Operations.PostAsync(requestBody); + + // Assert + response.Should().NotBeNull(); + + response.AtomicResults.Should().HaveCount(1); + DataInTeacherResponse teacherData = response.AtomicResults.ElementAt(0).Data.Should().BeOfType().Which; + + teacherData.Attributes.Should().NotBeNull(); + teacherData.Attributes.Name.Should().Be(newTeacher.Name); + teacherData.Attributes.EmailAddress.Should().Be(newTeacher.EmailAddress); + + long newTeacherId = long.Parse(teacherData.Id!); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Teacher teacherInDatabase = await dbContext.Teachers.FirstWithIdAsync(newTeacherId); + + teacherInDatabase.Name.Should().Be(newTeacher.Name); + teacherInDatabase.EmailAddress.Should().Be(newTeacher.EmailAddress); + }); + } + + [Fact] + public async Task Can_create_resource_with_attributes_and_relationships() + { + // Arrange + Student existingStudent = _fakers.Student.GenerateOne(); + Course existingCourse = _fakers.Course.GenerateOne(); + Enrollment newEnrollment = _fakers.Enrollment.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.AddInRange(existingStudent, existingCourse); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new AtomicOperationsClient(requestAdapter); + + OperationsRequestDocument requestBody = new() + { + AtomicOperations = + [ + new CreateEnrollmentOperation + { + Op = AddOperationCode.Add, + Data = new DataInCreateEnrollmentRequest + { + Type = ResourceType.Enrollments, + Attributes = new AttributesInCreateEnrollmentRequest + { + EnrolledAt = newEnrollment.EnrolledAt + }, + Relationships = new RelationshipsInCreateEnrollmentRequest + { + Course = new ToOneCourseInRequest + { + Data = new CourseIdentifierInRequest + { + Type = ResourceType.Courses, + Id = existingCourse.Id + } + }, + Student = new ToOneStudentInRequest + { + Data = new StudentIdentifierInRequest + { + Type = ResourceType.Students, + Id = existingStudent.StringId! + } + } + } + } + } + ] + }; + + // Act + OperationsResponseDocument? response = await apiClient.Operations.PostAsync(requestBody); + + // Assert + response.Should().NotBeNull(); + + response.AtomicResults.Should().HaveCount(1); + DataInEnrollmentResponse enrollmentData = response.AtomicResults.ElementAt(0).Data.Should().BeOfType().Which; + + enrollmentData.Attributes.Should().NotBeNull(); + enrollmentData.Attributes.EnrolledAt.Should().Be((Date)newEnrollment.EnrolledAt); + enrollmentData.Attributes.GraduatedAt.Should().BeNull(); + enrollmentData.Attributes.HasGraduated.Should().BeFalse(); + + long newEnrollmentId = long.Parse(enrollmentData.Id!); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Enrollment enrollmentInDatabase = await dbContext.Enrollments.FirstWithIdAsync(newEnrollmentId); + + enrollmentInDatabase.EnrolledAt.Should().Be(newEnrollment.EnrolledAt); + enrollmentInDatabase.GraduatedAt.Should().BeNull(); + enrollmentInDatabase.HasGraduated.Should().BeFalse(); + }); + } + + [Fact] + public async Task Can_create_resource_with_client_generated_ID() + { + // Arrange + Course newCourse = _fakers.Course.GenerateOne(); + newCourse.Id = Guid.NewGuid(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new AtomicOperationsClient(requestAdapter); + + OperationsRequestDocument requestBody = new() + { + AtomicOperations = + [ + new CreateCourseOperation + { + Op = AddOperationCode.Add, + Data = new DataInCreateCourseRequest + { + Type = ResourceType.Courses, + Id = newCourse.Id, + Attributes = new AttributesInCreateCourseRequest + { + Subject = newCourse.Subject + } + } + } + ] + }; + + // Act + OperationsResponseDocument? response = await apiClient.Operations.PostAsync(requestBody); + + // Assert + response.Should().BeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Course courseInDatabase = await dbContext.Courses.FirstWithIdAsync(newCourse.Id); + + courseInDatabase.Subject.Should().Be(newCourse.Subject); + courseInDatabase.Description.Should().BeNull(); + }); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicDeleteResourceTests.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicDeleteResourceTests.cs new file mode 100644 index 0000000000..3793fc2615 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicDeleteResourceTests.cs @@ -0,0 +1,81 @@ +using FluentAssertions; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode; +using OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.AtomicOperations; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.AtomicOperations; + +public sealed class AtomicDeleteResourceTests : IClassFixture, OperationsDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, OperationsDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly OperationsFakers _fakers; + + public AtomicDeleteResourceTests(IntegrationTestContext, OperationsDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseController(); + + _fakers = new OperationsFakers(testContext.Factory.Services); + } + + [Fact] + public async Task Can_delete_resource() + { + // Arrange + Enrollment existingEnrollment = _fakers.Enrollment.GenerateOne(); + existingEnrollment.Student = _fakers.Student.GenerateOne(); + existingEnrollment.Course = _fakers.Course.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Enrollments.Add(existingEnrollment); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new AtomicOperationsClient(requestAdapter); + + OperationsRequestDocument requestBody = new() + { + AtomicOperations = + [ + new DeleteEnrollmentOperation + { + Op = RemoveOperationCode.Remove, + Ref = new EnrollmentIdentifierInRequest + { + Type = ResourceType.Enrollments, + Id = existingEnrollment.StringId! + } + } + ] + }; + + // Act + OperationsResponseDocument? response = await apiClient.Operations.PostAsync(requestBody); + + // Assert + response.Should().BeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Enrollment? enrollmentInDatabase = await dbContext.Enrollments.FirstWithIdOrDefaultAsync(existingEnrollment.Id); + + enrollmentInDatabase.Should().BeNull(); + }); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicLocalIdTests.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicLocalIdTests.cs new file mode 100644 index 0000000000..cd44911339 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicLocalIdTests.cs @@ -0,0 +1,239 @@ +using FluentAssertions; +using Microsoft.EntityFrameworkCore; +using Microsoft.Kiota.Abstractions; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode; +using OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.AtomicOperations; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.AtomicOperations; + +public sealed class AtomicLocalIdTests : IClassFixture, OperationsDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, OperationsDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly OperationsFakers _fakers; + + public AtomicLocalIdTests(IntegrationTestContext, OperationsDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseController(); + + _fakers = new OperationsFakers(testContext.Factory.Services); + } + + [Fact] + public async Task Can_use_local_IDs() + { + // Arrange + Teacher newTeacher = _fakers.Teacher.GenerateOne(); + Course newCourse = _fakers.Course.GenerateOne(); + newCourse.Id = Guid.NewGuid(); + Student newStudent = _fakers.Student.GenerateOne(); + DateOnly newEnrolledAt = _fakers.Enrollment.GenerateOne().EnrolledAt; + + const string teacherLocalId = "teacher-1"; + const string studentLocalId = "student-1"; + const string enrollmentLocalId = "enrollment-1"; + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new AtomicOperationsClient(requestAdapter); + + OperationsRequestDocument requestBody = new() + { + AtomicOperations = + [ + new CreateTeacherOperation + { + Op = AddOperationCode.Add, + Data = new DataInCreateTeacherRequest + { + Type = ResourceType.Teachers, + Lid = teacherLocalId, + Attributes = new AttributesInCreateTeacherRequest + { + Name = newTeacher.Name, + EmailAddress = newTeacher.EmailAddress + } + } + }, + new CreateCourseOperation + { + Op = AddOperationCode.Add, + Data = new DataInCreateCourseRequest + { + Type = ResourceType.Courses, + Id = newCourse.Id, + Attributes = new AttributesInCreateCourseRequest + { + Subject = newCourse.Subject, + Description = newCourse.Description + } + } + }, + new AddToTeacherTeachesRelationshipOperation + { + Op = AddOperationCode.Add, + Ref = new TeacherTeachesRelationshipIdentifier + { + Type = TeacherResourceType.Teachers, + Lid = teacherLocalId, + Relationship = TeacherTeachesRelationshipName.Teaches + }, + Data = + [ + new CourseIdentifierInRequest + { + Type = ResourceType.Courses, + Id = newCourse.Id + } + ] + }, + new CreateStudentOperation + { + Op = AddOperationCode.Add, + Data = new DataInCreateStudentRequest + { + Type = ResourceType.Students, + Lid = studentLocalId, + Attributes = new AttributesInCreateStudentRequest + { + Name = newStudent.Name, + EmailAddress = newStudent.EmailAddress + } + } + }, + new CreateEnrollmentOperation + { + Op = AddOperationCode.Add, + Data = new DataInCreateEnrollmentRequest + { + Type = ResourceType.Enrollments, + Lid = enrollmentLocalId, + Attributes = new AttributesInCreateEnrollmentRequest + { + EnrolledAt = newEnrolledAt + }, + Relationships = new RelationshipsInCreateEnrollmentRequest + { + Course = new ToOneCourseInRequest + { + Data = new CourseIdentifierInRequest + { + Type = ResourceType.Courses, + Id = newCourse.Id + } + }, + Student = new ToOneStudentInRequest + { + Data = new StudentIdentifierInRequest + { + Type = ResourceType.Students, + Lid = studentLocalId + } + } + } + } + }, + new UpdateStudentMentorRelationshipOperation + { + Op = UpdateOperationCode.Update, + Ref = new StudentMentorRelationshipIdentifier + { + Type = StudentResourceType.Students, + Lid = studentLocalId, + Relationship = StudentMentorRelationshipName.Mentor + }, + Data = new TeacherIdentifierInRequest + { + Type = ResourceType.Teachers, + Lid = teacherLocalId + } + }, + new DeleteTeacherOperation + { + Op = RemoveOperationCode.Remove, + Ref = new TeacherIdentifierInRequest + { + Type = ResourceType.Teachers, + Lid = teacherLocalId + } + } + ] + }; + + // Act + OperationsResponseDocument? response = await apiClient.Operations.PostAsync(requestBody); + + // Assert + response.Should().NotBeNull(); + + response.AtomicResults.Should().HaveCount(7); + + DataInTeacherResponse teacherData = response.AtomicResults.ElementAt(0).Data.Should().BeOfType().Which; + teacherData.Attributes.Should().NotBeNull(); + teacherData.Attributes.Name.Should().Be(newTeacher.Name); + teacherData.Attributes.EmailAddress.Should().Be(newTeacher.EmailAddress); + long newTeacherId = long.Parse(teacherData.Id!); + + response.AtomicResults.ElementAt(1).Data.Should().BeNull(); + response.AtomicResults.ElementAt(2).Data.Should().BeNull(); + + DataInStudentResponse studentData = response.AtomicResults.ElementAt(3).Data.Should().BeOfType().Which; + studentData.Attributes.Should().NotBeNull(); + studentData.Attributes.Name.Should().Be(newStudent.Name); + studentData.Attributes.EmailAddress.Should().Be(newStudent.EmailAddress); + long newStudentId = long.Parse(studentData.Id!); + + DataInEnrollmentResponse enrollmentData = response.AtomicResults.ElementAt(4).Data.Should().BeOfType().Which; + enrollmentData.Attributes.Should().NotBeNull(); + enrollmentData.Attributes.EnrolledAt.Should().Be((Date)newEnrolledAt); + long newEnrollmentId = long.Parse(enrollmentData.Id!); + + response.AtomicResults.ElementAt(5).Data.Should().BeNull(); + response.AtomicResults.ElementAt(6).Data.Should().BeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Teacher? teacherInDatabase = await dbContext.Teachers.FirstWithIdOrDefaultAsync(newTeacherId); + teacherInDatabase.Should().BeNull(); + + Course courseInDatabase = await dbContext.Courses.Include(course => course.TaughtBy).FirstWithIdAsync(newCourse.Id); + courseInDatabase.Subject.Should().Be(newCourse.Subject); + courseInDatabase.Description.Should().Be(newCourse.Description); + courseInDatabase.TaughtBy.Should().BeEmpty(); + + Student studentInDatabase = await dbContext.Students.Include(student => student.Mentor).FirstWithIdAsync(newStudentId); + studentInDatabase.Name.Should().Be(newStudent.Name); + studentInDatabase.EmailAddress.Should().Be(newStudent.EmailAddress); + studentInDatabase.Mentor.Should().BeNull(); + + // @formatter:wrap_chained_method_calls chop_always + // @formatter:keep_existing_linebreaks true + + Enrollment enrollmentInDatabase = await dbContext.Enrollments + .Include(enrollment => enrollment.Course) + .Include(enrollment => enrollment.Student) + .FirstWithIdAsync(newEnrollmentId); + + // @formatter:keep_existing_linebreaks restore + // @formatter:wrap_chained_method_calls restore + + enrollmentInDatabase.EnrolledAt.Should().Be(newEnrolledAt); + enrollmentInDatabase.Course.Should().NotBeNull(); + enrollmentInDatabase.Course.Id.Should().Be(newCourse.Id); + enrollmentInDatabase.Student.Id.Should().Be(newStudentId); + }); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicRelationshipTests.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicRelationshipTests.cs new file mode 100644 index 0000000000..c07c688252 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicRelationshipTests.cs @@ -0,0 +1,281 @@ +using FluentAssertions; +using Microsoft.EntityFrameworkCore; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode; +using OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.AtomicOperations; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.AtomicOperations; + +public sealed class AtomicRelationshipTests : IClassFixture, OperationsDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, OperationsDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly OperationsFakers _fakers; + + public AtomicRelationshipTests(IntegrationTestContext, OperationsDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseController(); + + _fakers = new OperationsFakers(testContext.Factory.Services); + } + + [Fact] + public async Task Can_update_ToOne_relationship() + { + // Arrange + Enrollment existingEnrollment = _fakers.Enrollment.GenerateOne(); + existingEnrollment.Student = _fakers.Student.GenerateOne(); + existingEnrollment.Course = _fakers.Course.GenerateOne(); + + Student existingStudent = _fakers.Student.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.AddInRange(existingEnrollment, existingStudent); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new AtomicOperationsClient(requestAdapter); + + OperationsRequestDocument requestBody = new() + { + AtomicOperations = + [ + new UpdateEnrollmentStudentRelationshipOperation + { + Op = UpdateOperationCode.Update, + Ref = new EnrollmentStudentRelationshipIdentifier + { + Type = EnrollmentResourceType.Enrollments, + Id = existingEnrollment.StringId!, + Relationship = EnrollmentStudentRelationshipName.Student + }, + Data = new StudentIdentifierInRequest + { + Type = ResourceType.Students, + Id = existingStudent.StringId! + } + } + ] + }; + + // Act + OperationsResponseDocument? response = await apiClient.Operations.PostAsync(requestBody); + + // Assert + response.Should().BeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Enrollment enrollmentInDatabase = await dbContext.Enrollments.Include(enrollment => enrollment.Student).FirstWithIdAsync(existingEnrollment.Id); + + enrollmentInDatabase.Student.Should().NotBeNull(); + enrollmentInDatabase.Student.Id.Should().Be(existingStudent.Id); + }); + } + + [Fact] + public async Task Can_update_ToMany_relationship() + { + // Arrange + Teacher existingTeacher = _fakers.Teacher.GenerateOne(); + existingTeacher.Teaches = _fakers.Course.GenerateSet(1); + List existingCourses = _fakers.Course.GenerateList(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Add(existingTeacher); + dbContext.AddRange(existingCourses); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new AtomicOperationsClient(requestAdapter); + + OperationsRequestDocument requestBody = new() + { + AtomicOperations = + [ + new UpdateTeacherTeachesRelationshipOperation + { + Op = UpdateOperationCode.Update, + Ref = new TeacherTeachesRelationshipIdentifier + { + Id = existingTeacher.StringId!, + Type = TeacherResourceType.Teachers, + Relationship = TeacherTeachesRelationshipName.Teaches + }, + Data = + [ + new CourseIdentifierInRequest + { + Type = ResourceType.Courses, + Id = existingCourses.ElementAt(0).Id + }, + new CourseIdentifierInRequest + { + Type = ResourceType.Courses, + Id = existingCourses.ElementAt(1).Id + } + ] + } + ] + }; + + // Act + OperationsResponseDocument? response = await apiClient.Operations.PostAsync(requestBody); + + // Assert + response.Should().BeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Teacher teacherInDatabase = await dbContext.Teachers.Include(teacher => teacher.Teaches).FirstWithIdAsync(existingTeacher.Id); + + teacherInDatabase.Teaches.Should().HaveCount(2); + teacherInDatabase.Teaches.Should().ContainSingle(course => course.Id == existingCourses.ElementAt(0).Id); + teacherInDatabase.Teaches.Should().ContainSingle(course => course.Id == existingCourses.ElementAt(1).Id); + }); + } + + [Fact] + public async Task Can_add_to_ToMany_relationship() + { + // Arrange + Teacher existingTeacher = _fakers.Teacher.GenerateOne(); + existingTeacher.Teaches = _fakers.Course.GenerateSet(1); + List existingCourses = _fakers.Course.GenerateList(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Add(existingTeacher); + dbContext.AddRange(existingCourses); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new AtomicOperationsClient(requestAdapter); + + OperationsRequestDocument requestBody = new() + { + AtomicOperations = + [ + new AddToTeacherTeachesRelationshipOperation + { + Op = AddOperationCode.Add, + Ref = new TeacherTeachesRelationshipIdentifier + { + Type = TeacherResourceType.Teachers, + Id = existingTeacher.StringId!, + Relationship = TeacherTeachesRelationshipName.Teaches + }, + Data = + [ + new CourseIdentifierInRequest + { + Type = ResourceType.Courses, + Id = existingCourses.ElementAt(0).Id + }, + new CourseIdentifierInRequest + { + Type = ResourceType.Courses, + Id = existingCourses.ElementAt(1).Id + } + ] + } + ] + }; + + // Act + OperationsResponseDocument? response = await apiClient.Operations.PostAsync(requestBody); + + // Assert + response.Should().BeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Teacher teacherInDatabase = await dbContext.Teachers.Include(teacher => teacher.Teaches).FirstWithIdAsync(existingTeacher.Id); + + teacherInDatabase.Teaches.Should().HaveCount(3); + teacherInDatabase.Teaches.Should().ContainSingle(course => course.Id == existingTeacher.Teaches.ElementAt(0).Id); + teacherInDatabase.Teaches.Should().ContainSingle(course => course.Id == existingCourses.ElementAt(0).Id); + teacherInDatabase.Teaches.Should().ContainSingle(course => course.Id == existingCourses.ElementAt(1).Id); + }); + } + + [Fact] + public async Task Can_remove_from_ToMany_relationship() + { + // Arrange + Teacher existingTeacher = _fakers.Teacher.GenerateOne(); + existingTeacher.Teaches = _fakers.Course.GenerateSet(3); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Add(existingTeacher); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new AtomicOperationsClient(requestAdapter); + + OperationsRequestDocument requestBody = new() + { + AtomicOperations = + [ + new RemoveFromTeacherTeachesRelationshipOperation + { + Op = RemoveOperationCode.Remove, + Ref = new TeacherTeachesRelationshipIdentifier + { + Type = TeacherResourceType.Teachers, + Id = existingTeacher.StringId!, + Relationship = TeacherTeachesRelationshipName.Teaches + }, + Data = + [ + new CourseIdentifierInRequest + { + Type = ResourceType.Courses, + Id = existingTeacher.Teaches.ElementAt(0).Id + }, + new CourseIdentifierInRequest + { + Type = ResourceType.Courses, + Id = existingTeacher.Teaches.ElementAt(2).Id + } + ] + } + ] + }; + + // Act + OperationsResponseDocument? response = await apiClient.Operations.PostAsync(requestBody); + + // Assert + response.Should().BeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Teacher teacherInDatabase = await dbContext.Teachers.Include(teacher => teacher.Teaches).FirstWithIdAsync(existingTeacher.Id); + + teacherInDatabase.Teaches.Should().HaveCount(1); + teacherInDatabase.Teaches.ElementAt(0).Id.Should().Be(existingTeacher.Teaches.ElementAt(1).Id); + }); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicUpdateResourceTests.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicUpdateResourceTests.cs new file mode 100644 index 0000000000..c5aca4ec15 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicUpdateResourceTests.cs @@ -0,0 +1,265 @@ +using FluentAssertions; +using JsonApiDotNetCore.Resources; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Kiota.Abstractions; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode; +using OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.AtomicOperations; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.AtomicOperations; + +public sealed class AtomicUpdateResourceTests : IClassFixture, OperationsDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, OperationsDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly OperationsFakers _fakers; + + public AtomicUpdateResourceTests(IntegrationTestContext, OperationsDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseController(); + + testContext.ConfigureServices(services => services.AddScoped(typeof(IResourceChangeTracker<>), typeof(NeverSameResourceChangeTracker<>))); + + _fakers = new OperationsFakers(testContext.Factory.Services); + } + + [Fact] + public async Task Can_update_resource_with_attributes() + { + // Arrange + Student existingStudent = _fakers.Student.GenerateOne(); + string newName = _fakers.Student.GenerateOne().Name; + string? newEmailAddress = _fakers.Student.GenerateOne().EmailAddress; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Students.Add(existingStudent); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new AtomicOperationsClient(requestAdapter); + + OperationsRequestDocument requestBody = new() + { + AtomicOperations = + [ + new UpdateStudentOperation + { + Op = UpdateOperationCode.Update, + Data = new DataInUpdateStudentRequest + { + Type = ResourceType.Students, + Id = existingStudent.StringId!, + Attributes = new AttributesInUpdateStudentRequest + { + Name = newName, + EmailAddress = newEmailAddress + } + } + } + ] + }; + + // Act + OperationsResponseDocument? response = await apiClient.Operations.PostAsync(requestBody); + + // Assert + response.Should().NotBeNull(); + + response.AtomicResults.Should().HaveCount(1); + DataInStudentResponse studentData = response.AtomicResults.ElementAt(0).Data.Should().BeOfType().Which; + + studentData.Id.Should().Be(existingStudent.StringId); + studentData.Attributes.Should().NotBeNull(); + studentData.Attributes.Name.Should().Be(newName); + studentData.Attributes.EmailAddress.Should().Be(newEmailAddress); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Student studentInDatabase = await dbContext.Students.FirstWithIdAsync(existingStudent.Id); + + studentInDatabase.Name.Should().Be(newName); + studentInDatabase.EmailAddress.Should().Be(newEmailAddress); + }); + } + + [Fact] + public async Task Can_update_resource_with_attributes_using_ref() + { + // Arrange + Student existingStudent = _fakers.Student.GenerateOne(); + string? newEmailAddress = _fakers.Student.GenerateOne().EmailAddress; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Students.Add(existingStudent); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new AtomicOperationsClient(requestAdapter); + + OperationsRequestDocument requestBody = new() + { + AtomicOperations = + [ + new UpdateStudentOperation + { + Op = UpdateOperationCode.Update, + Ref = new StudentIdentifierInRequest + { + Type = ResourceType.Students, + Id = existingStudent.StringId! + }, + Data = new DataInUpdateStudentRequest + { + Type = ResourceType.Students, + Id = existingStudent.StringId!, + Attributes = new AttributesInUpdateStudentRequest + { + EmailAddress = newEmailAddress + } + } + } + ] + }; + + // Act + OperationsResponseDocument? response = await apiClient.Operations.PostAsync(requestBody); + + // Assert + response.Should().NotBeNull(); + + response.AtomicResults.Should().HaveCount(1); + DataInStudentResponse studentData = response.AtomicResults.ElementAt(0).Data.Should().BeOfType().Which; + + studentData.Id.Should().Be(existingStudent.StringId); + studentData.Attributes.Should().NotBeNull(); + studentData.Attributes.Name.Should().Be(existingStudent.Name); + studentData.Attributes.EmailAddress.Should().Be(newEmailAddress); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Student studentInDatabase = await dbContext.Students.FirstWithIdAsync(existingStudent.Id); + + studentInDatabase.Name.Should().Be(existingStudent.Name); + studentInDatabase.EmailAddress.Should().Be(newEmailAddress); + }); + } + + [Fact] + public async Task Can_update_resource_with_attributes_and_relationships() + { + // Arrange + Enrollment existingEnrollment = _fakers.Enrollment.GenerateOne(); + existingEnrollment.Student = _fakers.Student.GenerateOne(); + existingEnrollment.Course = _fakers.Course.GenerateOne(); + + Student existingStudent = _fakers.Student.GenerateOne(); + Course existingCourse = _fakers.Course.GenerateOne(); + DateOnly newEnrolledAt = _fakers.Enrollment.GenerateOne().EnrolledAt; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.AddInRange(existingEnrollment, existingStudent, existingCourse); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new AtomicOperationsClient(requestAdapter); + + OperationsRequestDocument requestBody = new() + { + AtomicOperations = + [ + new UpdateEnrollmentOperation + { + Op = UpdateOperationCode.Update, + Data = new DataInUpdateEnrollmentRequest + { + Type = ResourceType.Enrollments, + Id = existingEnrollment.StringId!, + Attributes = new AttributesInUpdateEnrollmentRequest + { + EnrolledAt = newEnrolledAt + }, + Relationships = new RelationshipsInUpdateEnrollmentRequest + { + Course = new ToOneCourseInRequest + { + Data = new CourseIdentifierInRequest + { + Type = ResourceType.Courses, + Id = existingCourse.Id + } + }, + Student = new ToOneStudentInRequest + { + Data = new StudentIdentifierInRequest + { + Type = ResourceType.Students, + Id = existingStudent.StringId! + } + } + } + } + } + ] + }; + + // Act + OperationsResponseDocument? response = await apiClient.Operations.PostAsync(requestBody); + + // Assert + response.Should().NotBeNull(); + + response.AtomicResults.Should().HaveCount(1); + DataInEnrollmentResponse enrollmentData = response.AtomicResults.ElementAt(0).Data.Should().BeOfType().Which; + + enrollmentData.Id.Should().Be(existingEnrollment.StringId); + enrollmentData.Attributes.Should().NotBeNull(); + enrollmentData.Attributes.EnrolledAt.Should().Be((Date)newEnrolledAt); + enrollmentData.Attributes.GraduatedAt.Should().Be((Date)existingEnrollment.GraduatedAt!.Value); + enrollmentData.Attributes.HasGraduated.Should().Be(existingEnrollment.HasGraduated); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + // @formatter:wrap_chained_method_calls chop_always + // @formatter:keep_existing_linebreaks true + + Enrollment enrollmentInDatabase = await dbContext.Enrollments + .Include(enrollment => enrollment.Student) + .Include(enrollment => enrollment.Course) + .FirstWithIdAsync(existingEnrollment.Id); + + // @formatter:keep_existing_linebreaks restore + // @formatter:wrap_chained_method_calls restore + + enrollmentInDatabase.EnrolledAt.Should().Be(newEnrolledAt); + enrollmentInDatabase.GraduatedAt.Should().Be(existingEnrollment.GraduatedAt); + enrollmentInDatabase.HasGraduated.Should().Be(existingEnrollment.HasGraduated); + + enrollmentInDatabase.Student.Should().NotBeNull(); + enrollmentInDatabase.Student.Id.Should().Be(existingStudent.Id); + + enrollmentInDatabase.Course.Should().NotBeNull(); + enrollmentInDatabase.Course.Id.Should().Be(existingCourse.Id); + }); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/AtomicOperationsClient.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/AtomicOperationsClient.cs new file mode 100644 index 0000000000..c55a40b9d4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/AtomicOperationsClient.cs @@ -0,0 +1,54 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using Microsoft.Kiota.Serialization.Form; +using Microsoft.Kiota.Serialization.Json; +using Microsoft.Kiota.Serialization.Multipart; +using Microsoft.Kiota.Serialization.Text; +using OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Operations; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode +{ + /// + /// The main entry point of the SDK, exposes the configuration and the fluent API. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AtomicOperationsClient : BaseRequestBuilder + { + /// The operations property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Operations.OperationsRequestBuilder Operations + { + get => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Operations.OperationsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The backing store to use for the models. + /// The request adapter to use to execute the requests. + public AtomicOperationsClient(IRequestAdapter requestAdapter, IBackingStoreFactory backingStore = default) : base(requestAdapter, "{+baseurl}", new Dictionary()) + { + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + if (string.IsNullOrEmpty(RequestAdapter.BaseUrl)) + { + RequestAdapter.BaseUrl = "http://localhost"; + } + PathParameters.TryAdd("baseurl", RequestAdapter.BaseUrl); + RequestAdapter.EnableBackingStore(backingStore); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AddOperationCode.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AddOperationCode.cs new file mode 100644 index 0000000000..b3cdfa02a1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AddOperationCode.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum AddOperationCode + #pragma warning restore CS1591 + { + [EnumMember(Value = "add")] + #pragma warning disable CS1591 + Add, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AddToCourseEnrollmentsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AddToCourseEnrollmentsRelationshipOperation.cs new file mode 100644 index 0000000000..1a7bbf708b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AddToCourseEnrollmentsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AddToCourseEnrollmentsRelationshipOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseEnrollmentsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddToCourseEnrollmentsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddToCourseEnrollmentsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseEnrollmentsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AddToCourseTaughtByRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AddToCourseTaughtByRelationshipOperation.cs new file mode 100644 index 0000000000..9826e2e5e5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AddToCourseTaughtByRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AddToCourseTaughtByRelationshipOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseTaughtByRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddToCourseTaughtByRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddToCourseTaughtByRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseTaughtByRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AddToStudentEnrollmentsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AddToStudentEnrollmentsRelationshipOperation.cs new file mode 100644 index 0000000000..4378cb260f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AddToStudentEnrollmentsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AddToStudentEnrollmentsRelationshipOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentEnrollmentsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddToStudentEnrollmentsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddToStudentEnrollmentsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentEnrollmentsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AddToTeacherMentorsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AddToTeacherMentorsRelationshipOperation.cs new file mode 100644 index 0000000000..d2365eb79e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AddToTeacherMentorsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AddToTeacherMentorsRelationshipOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherMentorsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddToTeacherMentorsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddToTeacherMentorsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherMentorsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AddToTeacherTeachesRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AddToTeacherTeachesRelationshipOperation.cs new file mode 100644 index 0000000000..052b93ccd2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AddToTeacherTeachesRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AddToTeacherTeachesRelationshipOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherTeachesRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddToTeacherTeachesRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddToTeacherTeachesRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherTeachesRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AtomicOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AtomicOperation.cs new file mode 100644 index 0000000000..08b81af5ae --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AtomicOperation.cs @@ -0,0 +1,109 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AtomicOperation : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The openapiDiscriminator property + public string? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AtomicOperation() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "addCourse" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CreateCourseOperation(), + "addEnrollment" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CreateEnrollmentOperation(), + "addStudent" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CreateStudentOperation(), + "addTeacher" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CreateTeacherOperation(), + "addToCourseEnrollments" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddToCourseEnrollmentsRelationshipOperation(), + "addToCourseTaughtBy" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddToCourseTaughtByRelationshipOperation(), + "addToStudentEnrollments" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddToStudentEnrollmentsRelationshipOperation(), + "addToTeacherMentors" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddToTeacherMentorsRelationshipOperation(), + "addToTeacherTeaches" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddToTeacherTeachesRelationshipOperation(), + "removeCourse" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DeleteCourseOperation(), + "removeEnrollment" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DeleteEnrollmentOperation(), + "removeFromStudentEnrollments" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RemoveFromStudentEnrollmentsRelationshipOperation(), + "removeFromTeacherMentors" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RemoveFromTeacherMentorsRelationshipOperation(), + "removeFromTeacherTeaches" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RemoveFromTeacherTeachesRelationshipOperation(), + "removeTeacher" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DeleteTeacherOperation(), + "updateCourse" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateCourseOperation(), + "updateCourseEnrollments" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateCourseEnrollmentsRelationshipOperation(), + "updateEnrollment" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateEnrollmentOperation(), + "updateEnrollmentCourse" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateEnrollmentCourseRelationshipOperation(), + "updateEnrollmentStudent" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateEnrollmentStudentRelationshipOperation(), + "updateStudent" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateStudentOperation(), + "updateStudentEnrollments" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateStudentEnrollmentsRelationshipOperation(), + "updateStudentMentor" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateStudentMentorRelationshipOperation(), + "updateTeacher" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateTeacherOperation(), + "updateTeacherMentors" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateTeacherMentorsRelationshipOperation(), + "updateTeacherTeaches" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateTeacherTeachesRelationshipOperation(), + _ => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteStringValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AtomicResult.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AtomicResult.cs new file mode 100644 index 0000000000..2904a10156 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AtomicResult.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AtomicResult : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AtomicResult() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicResult CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicResult(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInCourseResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInCourseResponse.cs new file mode 100644 index 0000000000..df6e6c79e9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInCourseResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCourseResponse : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The description property + public string? Description + { + get { return BackingStore?.Get("description"); } + set { BackingStore?.Set("description", value); } + } + + /// The subject property + public string? Subject + { + get { return BackingStore?.Get("subject"); } + set { BackingStore?.Set("subject", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCourseResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCourseResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "description", n => { Description = n.GetStringValue(); } }, + { "subject", n => { Subject = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("description", Description); + writer.WriteStringValue("subject", Subject); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInCreateCourseRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInCreateCourseRequest.cs new file mode 100644 index 0000000000..ba7579971a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInCreateCourseRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateCourseRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The description property + public string? Description + { + get { return BackingStore?.Get("description"); } + set { BackingStore?.Set("description", value); } + } + + /// The subject property + public string? Subject + { + get { return BackingStore?.Get("subject"); } + set { BackingStore?.Set("subject", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateCourseRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateCourseRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "description", n => { Description = n.GetStringValue(); } }, + { "subject", n => { Subject = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("description", Description); + writer.WriteStringValue("subject", Subject); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInCreateEnrollmentRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInCreateEnrollmentRequest.cs new file mode 100644 index 0000000000..40a8d42f00 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInCreateEnrollmentRequest.cs @@ -0,0 +1,69 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateEnrollmentRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The enrolledAt property + public Date? EnrolledAt + { + get { return BackingStore?.Get("enrolledAt"); } + set { BackingStore?.Set("enrolledAt", value); } + } + + /// The graduatedAt property + public Date? GraduatedAt + { + get { return BackingStore?.Get("graduatedAt"); } + set { BackingStore?.Set("graduatedAt", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateEnrollmentRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateEnrollmentRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "enrolledAt", n => { EnrolledAt = n.GetDateValue(); } }, + { "graduatedAt", n => { GraduatedAt = n.GetDateValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteDateValue("enrolledAt", EnrolledAt); + writer.WriteDateValue("graduatedAt", GraduatedAt); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInCreateRequest.cs new file mode 100644 index 0000000000..637d585be2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInCreateRequest.cs @@ -0,0 +1,78 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "courses" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateCourseRequest(), + "enrollments" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateEnrollmentRequest(), + "students" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateStudentRequest(), + "teachers" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateTeacherRequest(), + _ => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInCreateStudentRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInCreateStudentRequest.cs new file mode 100644 index 0000000000..fe38dd276a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInCreateStudentRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateStudentRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The emailAddress property + public string? EmailAddress + { + get { return BackingStore?.Get("emailAddress"); } + set { BackingStore?.Set("emailAddress", value); } + } + + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateStudentRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateStudentRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "emailAddress", n => { EmailAddress = n.GetStringValue(); } }, + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("emailAddress", EmailAddress); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInCreateTeacherRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInCreateTeacherRequest.cs new file mode 100644 index 0000000000..892163936d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInCreateTeacherRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateTeacherRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The emailAddress property + public string? EmailAddress + { + get { return BackingStore?.Get("emailAddress"); } + set { BackingStore?.Set("emailAddress", value); } + } + + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateTeacherRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateTeacherRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "emailAddress", n => { EmailAddress = n.GetStringValue(); } }, + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("emailAddress", EmailAddress); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInEnrollmentResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInEnrollmentResponse.cs new file mode 100644 index 0000000000..d771e3c9ec --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInEnrollmentResponse.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInEnrollmentResponse : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The enrolledAt property + public Date? EnrolledAt + { + get { return BackingStore?.Get("enrolledAt"); } + set { BackingStore?.Set("enrolledAt", value); } + } + + /// The graduatedAt property + public Date? GraduatedAt + { + get { return BackingStore?.Get("graduatedAt"); } + set { BackingStore?.Set("graduatedAt", value); } + } + + /// The hasGraduated property + public bool? HasGraduated + { + get { return BackingStore?.Get("hasGraduated"); } + set { BackingStore?.Set("hasGraduated", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInEnrollmentResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInEnrollmentResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "enrolledAt", n => { EnrolledAt = n.GetDateValue(); } }, + { "graduatedAt", n => { GraduatedAt = n.GetDateValue(); } }, + { "hasGraduated", n => { HasGraduated = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteDateValue("enrolledAt", EnrolledAt); + writer.WriteDateValue("graduatedAt", GraduatedAt); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInResponse.cs new file mode 100644 index 0000000000..b2fa62f1bb --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInResponse.cs @@ -0,0 +1,78 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "courses" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCourseResponse(), + "enrollments" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInEnrollmentResponse(), + "students" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInStudentResponse(), + "teachers" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInTeacherResponse(), + _ => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInStudentResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInStudentResponse.cs new file mode 100644 index 0000000000..5246f61c11 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInStudentResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInStudentResponse : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The emailAddress property + public string? EmailAddress + { + get { return BackingStore?.Get("emailAddress"); } + set { BackingStore?.Set("emailAddress", value); } + } + + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInStudentResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInStudentResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "emailAddress", n => { EmailAddress = n.GetStringValue(); } }, + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("emailAddress", EmailAddress); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInTeacherResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInTeacherResponse.cs new file mode 100644 index 0000000000..be526f6a13 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInTeacherResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInTeacherResponse : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The emailAddress property + public string? EmailAddress + { + get { return BackingStore?.Get("emailAddress"); } + set { BackingStore?.Set("emailAddress", value); } + } + + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInTeacherResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInTeacherResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "emailAddress", n => { EmailAddress = n.GetStringValue(); } }, + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("emailAddress", EmailAddress); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInUpdateCourseRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInUpdateCourseRequest.cs new file mode 100644 index 0000000000..4424257f52 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInUpdateCourseRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateCourseRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The description property + public string? Description + { + get { return BackingStore?.Get("description"); } + set { BackingStore?.Set("description", value); } + } + + /// The subject property + public string? Subject + { + get { return BackingStore?.Get("subject"); } + set { BackingStore?.Set("subject", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateCourseRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateCourseRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "description", n => { Description = n.GetStringValue(); } }, + { "subject", n => { Subject = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("description", Description); + writer.WriteStringValue("subject", Subject); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInUpdateEnrollmentRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInUpdateEnrollmentRequest.cs new file mode 100644 index 0000000000..94c926c8a7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInUpdateEnrollmentRequest.cs @@ -0,0 +1,69 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateEnrollmentRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The enrolledAt property + public Date? EnrolledAt + { + get { return BackingStore?.Get("enrolledAt"); } + set { BackingStore?.Set("enrolledAt", value); } + } + + /// The graduatedAt property + public Date? GraduatedAt + { + get { return BackingStore?.Get("graduatedAt"); } + set { BackingStore?.Set("graduatedAt", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateEnrollmentRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateEnrollmentRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "enrolledAt", n => { EnrolledAt = n.GetDateValue(); } }, + { "graduatedAt", n => { GraduatedAt = n.GetDateValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteDateValue("enrolledAt", EnrolledAt); + writer.WriteDateValue("graduatedAt", GraduatedAt); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInUpdateRequest.cs new file mode 100644 index 0000000000..773a8e7ff4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInUpdateRequest.cs @@ -0,0 +1,78 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "courses" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateCourseRequest(), + "enrollments" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateEnrollmentRequest(), + "students" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateStudentRequest(), + "teachers" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateTeacherRequest(), + _ => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInUpdateStudentRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInUpdateStudentRequest.cs new file mode 100644 index 0000000000..6617a18ac0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInUpdateStudentRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateStudentRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The emailAddress property + public string? EmailAddress + { + get { return BackingStore?.Get("emailAddress"); } + set { BackingStore?.Set("emailAddress", value); } + } + + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateStudentRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateStudentRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "emailAddress", n => { EmailAddress = n.GetStringValue(); } }, + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("emailAddress", EmailAddress); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInUpdateTeacherRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInUpdateTeacherRequest.cs new file mode 100644 index 0000000000..a06272523e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/AttributesInUpdateTeacherRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateTeacherRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The emailAddress property + public string? EmailAddress + { + get { return BackingStore?.Get("emailAddress"); } + set { BackingStore?.Set("emailAddress", value); } + } + + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateTeacherRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateTeacherRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "emailAddress", n => { EmailAddress = n.GetStringValue(); } }, + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("emailAddress", EmailAddress); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CourseEnrollmentsRelationshipIdentifier.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CourseEnrollmentsRelationshipIdentifier.cs new file mode 100644 index 0000000000..aec552813d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CourseEnrollmentsRelationshipIdentifier.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CourseEnrollmentsRelationshipIdentifier : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationship property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseEnrollmentsRelationshipName? Relationship + { + get { return BackingStore?.Get("relationship"); } + set { BackingStore?.Set("relationship", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CourseEnrollmentsRelationshipIdentifier() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseEnrollmentsRelationshipIdentifier CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseEnrollmentsRelationshipIdentifier(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetGuidValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationship", n => { Relationship = n.GetEnumValue(); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteGuidValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteEnumValue("relationship", Relationship); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CourseEnrollmentsRelationshipName.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CourseEnrollmentsRelationshipName.cs new file mode 100644 index 0000000000..39d9635743 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CourseEnrollmentsRelationshipName.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum CourseEnrollmentsRelationshipName + #pragma warning restore CS1591 + { + [EnumMember(Value = "enrollments")] + #pragma warning disable CS1591 + Enrollments, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CourseIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CourseIdentifierInRequest.cs new file mode 100644 index 0000000000..1533147c0e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CourseIdentifierInRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CourseIdentifierInRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetGuidValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteGuidValue("id", Id); + writer.WriteStringValue("lid", Lid); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CourseIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CourseIdentifierInResponse.cs new file mode 100644 index 0000000000..10c23cdb90 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CourseIdentifierInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CourseIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CourseIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetGuidValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteGuidValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CourseResourceType.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CourseResourceType.cs new file mode 100644 index 0000000000..718985799f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CourseResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum CourseResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "courses")] + #pragma warning disable CS1591 + Courses, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CourseTaughtByRelationshipIdentifier.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CourseTaughtByRelationshipIdentifier.cs new file mode 100644 index 0000000000..62b9885b89 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CourseTaughtByRelationshipIdentifier.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CourseTaughtByRelationshipIdentifier : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationship property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseTaughtByRelationshipName? Relationship + { + get { return BackingStore?.Get("relationship"); } + set { BackingStore?.Set("relationship", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CourseTaughtByRelationshipIdentifier() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseTaughtByRelationshipIdentifier CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseTaughtByRelationshipIdentifier(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetGuidValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationship", n => { Relationship = n.GetEnumValue(); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteGuidValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteEnumValue("relationship", Relationship); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CourseTaughtByRelationshipName.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CourseTaughtByRelationshipName.cs new file mode 100644 index 0000000000..a0492c5178 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CourseTaughtByRelationshipName.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum CourseTaughtByRelationshipName + #pragma warning restore CS1591 + { + [EnumMember(Value = "taughtBy")] + #pragma warning disable CS1591 + TaughtBy, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CreateCourseOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CreateCourseOperation.cs new file mode 100644 index 0000000000..8b91fafae9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CreateCourseOperation.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateCourseOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInCreateCourseRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CreateCourseOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CreateCourseOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInCreateCourseRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CreateEnrollmentOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CreateEnrollmentOperation.cs new file mode 100644 index 0000000000..c81925259d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CreateEnrollmentOperation.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateEnrollmentOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInCreateEnrollmentRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CreateEnrollmentOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CreateEnrollmentOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInCreateEnrollmentRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CreateStudentOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CreateStudentOperation.cs new file mode 100644 index 0000000000..5784567050 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CreateStudentOperation.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateStudentOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInCreateStudentRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CreateStudentOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CreateStudentOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInCreateStudentRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CreateTeacherOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CreateTeacherOperation.cs new file mode 100644 index 0000000000..2409823479 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/CreateTeacherOperation.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateTeacherOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInCreateTeacherRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AddOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CreateTeacherOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CreateTeacherOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInCreateTeacherRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInCourseResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInCourseResponse.cs new file mode 100644 index 0000000000..88d5b209d4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInCourseResponse.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCourseResponse : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCourseResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCourseResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInCourseResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInCourseResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCourseResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetGuidValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCourseResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteGuidValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInCreateCourseRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInCreateCourseRequest.cs new file mode 100644 index 0000000000..70c3e9b657 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInCreateCourseRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateCourseRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateCourseRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateCourseRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInCreateCourseRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInCreateCourseRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateCourseRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetGuidValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateCourseRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteGuidValue("id", Id); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInCreateEnrollmentRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInCreateEnrollmentRequest.cs new file mode 100644 index 0000000000..2ed42a7b79 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInCreateEnrollmentRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateEnrollmentRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateEnrollmentRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateEnrollmentRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInCreateEnrollmentRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInCreateEnrollmentRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateEnrollmentRequest.CreateFromDiscriminatorValue); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateEnrollmentRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInCreateStudentRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInCreateStudentRequest.cs new file mode 100644 index 0000000000..1dfe2e6f34 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInCreateStudentRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateStudentRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateStudentRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateStudentRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInCreateStudentRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInCreateStudentRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateStudentRequest.CreateFromDiscriminatorValue); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateStudentRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInCreateTeacherRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInCreateTeacherRequest.cs new file mode 100644 index 0000000000..401be5db98 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInCreateTeacherRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateTeacherRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateTeacherRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateTeacherRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInCreateTeacherRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInCreateTeacherRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInCreateTeacherRequest.CreateFromDiscriminatorValue); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateTeacherRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInEnrollmentResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInEnrollmentResponse.cs new file mode 100644 index 0000000000..d975990b73 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInEnrollmentResponse.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInEnrollmentResponse : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInEnrollmentResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInEnrollmentResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInEnrollmentResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInEnrollmentResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInEnrollmentResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInEnrollmentResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInStudentResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInStudentResponse.cs new file mode 100644 index 0000000000..b2f951287c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInStudentResponse.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInStudentResponse : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInStudentResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInStudentResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInStudentResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInStudentResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInStudentResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInStudentResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInTeacherResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInTeacherResponse.cs new file mode 100644 index 0000000000..a18f14d2df --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInTeacherResponse.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInTeacherResponse : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInTeacherResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInTeacherResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInTeacherResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInTeacherResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInTeacherResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInTeacherResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInUpdateCourseRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInUpdateCourseRequest.cs new file mode 100644 index 0000000000..dac21081ee --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInUpdateCourseRequest.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateCourseRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateCourseRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateCourseRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInUpdateCourseRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInUpdateCourseRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateCourseRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetGuidValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateCourseRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteGuidValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInUpdateEnrollmentRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInUpdateEnrollmentRequest.cs new file mode 100644 index 0000000000..ac1c9a49ec --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInUpdateEnrollmentRequest.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateEnrollmentRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateEnrollmentRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateEnrollmentRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInUpdateEnrollmentRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInUpdateEnrollmentRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateEnrollmentRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateEnrollmentRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInUpdateStudentRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInUpdateStudentRequest.cs new file mode 100644 index 0000000000..14f92de1ca --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInUpdateStudentRequest.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateStudentRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateStudentRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateStudentRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInUpdateStudentRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInUpdateStudentRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateStudentRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateStudentRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInUpdateTeacherRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInUpdateTeacherRequest.cs new file mode 100644 index 0000000000..6e4c69ea87 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DataInUpdateTeacherRequest.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateTeacherRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateTeacherRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateTeacherRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInUpdateTeacherRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInUpdateTeacherRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AttributesInUpdateTeacherRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateTeacherRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DeleteCourseOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DeleteCourseOperation.cs new file mode 100644 index 0000000000..25dbaeb0a9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DeleteCourseOperation.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DeleteCourseOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RemoveOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseIdentifierInRequest? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DeleteCourseOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DeleteCourseOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseIdentifierInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DeleteEnrollmentOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DeleteEnrollmentOperation.cs new file mode 100644 index 0000000000..9a7faec4ba --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DeleteEnrollmentOperation.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DeleteEnrollmentOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RemoveOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentIdentifierInRequest? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DeleteEnrollmentOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DeleteEnrollmentOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentIdentifierInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DeleteTeacherOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DeleteTeacherOperation.cs new file mode 100644 index 0000000000..d0dfa14fe8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/DeleteTeacherOperation.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DeleteTeacherOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RemoveOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherIdentifierInRequest? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DeleteTeacherOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DeleteTeacherOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherIdentifierInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/EnrollmentCourseRelationshipIdentifier.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/EnrollmentCourseRelationshipIdentifier.cs new file mode 100644 index 0000000000..8f812e0c87 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/EnrollmentCourseRelationshipIdentifier.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class EnrollmentCourseRelationshipIdentifier : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationship property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentCourseRelationshipName? Relationship + { + get { return BackingStore?.Get("relationship"); } + set { BackingStore?.Set("relationship", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public EnrollmentCourseRelationshipIdentifier() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentCourseRelationshipIdentifier CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentCourseRelationshipIdentifier(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationship", n => { Relationship = n.GetEnumValue(); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteEnumValue("relationship", Relationship); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/EnrollmentCourseRelationshipName.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/EnrollmentCourseRelationshipName.cs new file mode 100644 index 0000000000..66677b8bd7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/EnrollmentCourseRelationshipName.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum EnrollmentCourseRelationshipName + #pragma warning restore CS1591 + { + [EnumMember(Value = "course")] + #pragma warning disable CS1591 + Course, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/EnrollmentIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/EnrollmentIdentifierInRequest.cs new file mode 100644 index 0000000000..cf87ae7eaa --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/EnrollmentIdentifierInRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class EnrollmentIdentifierInRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/EnrollmentIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/EnrollmentIdentifierInResponse.cs new file mode 100644 index 0000000000..8b11b4d6fa --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/EnrollmentIdentifierInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class EnrollmentIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public EnrollmentIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/EnrollmentResourceType.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/EnrollmentResourceType.cs new file mode 100644 index 0000000000..35a458ed81 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/EnrollmentResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum EnrollmentResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "enrollments")] + #pragma warning disable CS1591 + Enrollments, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/EnrollmentStudentRelationshipIdentifier.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/EnrollmentStudentRelationshipIdentifier.cs new file mode 100644 index 0000000000..99fd722766 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/EnrollmentStudentRelationshipIdentifier.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class EnrollmentStudentRelationshipIdentifier : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationship property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentStudentRelationshipName? Relationship + { + get { return BackingStore?.Get("relationship"); } + set { BackingStore?.Set("relationship", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public EnrollmentStudentRelationshipIdentifier() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentStudentRelationshipIdentifier CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentStudentRelationshipIdentifier(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationship", n => { Relationship = n.GetEnumValue(); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteEnumValue("relationship", Relationship); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/EnrollmentStudentRelationshipName.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/EnrollmentStudentRelationshipName.cs new file mode 100644 index 0000000000..d241bd62cb --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/EnrollmentStudentRelationshipName.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum EnrollmentStudentRelationshipName + #pragma warning restore CS1591 + { + [EnumMember(Value = "student")] + #pragma warning disable CS1591 + Student, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ErrorLinks.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ErrorLinks.cs new file mode 100644 index 0000000000..272918934e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ErrorLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// The about property + public string? About + { + get { return BackingStore?.Get("about"); } + set { BackingStore?.Set("about", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The type property + public string? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ErrorLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ErrorLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "about", n => { About = n.GetStringValue(); } }, + { "type", n => { Type = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("about", About); + writer.WriteStringValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ErrorObject.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ErrorObject.cs new file mode 100644 index 0000000000..7a14b36845 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ErrorObject.cs @@ -0,0 +1,133 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorObject : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The code property + public string? Code + { + get { return BackingStore?.Get("code"); } + set { BackingStore?.Set("code", value); } + } + + /// The detail property + public string? Detail + { + get { return BackingStore?.Get("detail"); } + set { BackingStore?.Set("detail", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ErrorLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The source property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ErrorSource? Source + { + get { return BackingStore?.Get("source"); } + set { BackingStore?.Set("source", value); } + } + + /// The status property + public string? Status + { + get { return BackingStore?.Get("status"); } + set { BackingStore?.Set("status", value); } + } + + /// The title property + public string? Title + { + get { return BackingStore?.Get("title"); } + set { BackingStore?.Set("title", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorObject() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ErrorObject CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ErrorObject(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "code", n => { Code = n.GetStringValue(); } }, + { "detail", n => { Detail = n.GetStringValue(); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ErrorLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "source", n => { Source = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ErrorSource.CreateFromDiscriminatorValue); } }, + { "status", n => { Status = n.GetStringValue(); } }, + { "title", n => { Title = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("code", Code); + writer.WriteStringValue("detail", Detail); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + writer.WriteObjectValue("source", Source); + writer.WriteStringValue("status", Status); + writer.WriteStringValue("title", Title); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ErrorResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ErrorResponseDocument.cs new file mode 100644 index 0000000000..69b0fdeb9c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ErrorResponseDocument.cs @@ -0,0 +1,101 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorResponseDocument : ApiException, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The errors property + public List? Errors + { + get { return BackingStore?.Get?>("errors"); } + set { BackingStore?.Set("errors", value); } + } + + /// The jsonapi property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Jsonapi? Jsonapi + { + get { return BackingStore?.Get("jsonapi"); } + set { BackingStore?.Set("jsonapi", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ErrorTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The primary error message. + public override string Message { get => base.Message; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ErrorResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ErrorResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "errors", n => { Errors = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ErrorObject.CreateFromDiscriminatorValue)?.AsList(); } }, + { "jsonapi", n => { Jsonapi = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Jsonapi.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ErrorTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("errors", Errors); + writer.WriteObjectValue("jsonapi", Jsonapi); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ErrorSource.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ErrorSource.cs new file mode 100644 index 0000000000..ab85081caa --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ErrorSource.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorSource : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The header property + public string? Header + { + get { return BackingStore?.Get("header"); } + set { BackingStore?.Set("header", value); } + } + + /// The parameter property + public string? Parameter + { + get { return BackingStore?.Get("parameter"); } + set { BackingStore?.Set("parameter", value); } + } + + /// The pointer property + public string? Pointer + { + get { return BackingStore?.Get("pointer"); } + set { BackingStore?.Set("pointer", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorSource() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ErrorSource CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ErrorSource(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "header", n => { Header = n.GetStringValue(); } }, + { "parameter", n => { Parameter = n.GetStringValue(); } }, + { "pointer", n => { Pointer = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("header", Header); + writer.WriteStringValue("parameter", Parameter); + writer.WriteStringValue("pointer", Pointer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ErrorTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ErrorTopLevelLinks.cs new file mode 100644 index 0000000000..f870eba588 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ErrorTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ErrorTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ErrorTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/IdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/IdentifierInRequest.cs new file mode 100644 index 0000000000..3c4820a647 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/IdentifierInRequest.cs @@ -0,0 +1,87 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class IdentifierInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public IdentifierInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.IdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "courses" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseIdentifierInRequest(), + "enrollments" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentIdentifierInRequest(), + "students" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentIdentifierInRequest(), + "teachers" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherIdentifierInRequest(), + _ => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.IdentifierInRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/Jsonapi.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/Jsonapi.cs new file mode 100644 index 0000000000..1c285062e5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/Jsonapi.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class Jsonapi : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The ext property + public List? Ext + { + get { return BackingStore?.Get?>("ext"); } + set { BackingStore?.Set("ext", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The profile property + public List? Profile + { + get { return BackingStore?.Get?>("profile"); } + set { BackingStore?.Set("profile", value); } + } + + /// The version property + public string? Version + { + get { return BackingStore?.Get("version"); } + set { BackingStore?.Set("version", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public Jsonapi() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Jsonapi CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Jsonapi(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "ext", n => { Ext = n.GetCollectionOfPrimitiveValues()?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "profile", n => { Profile = n.GetCollectionOfPrimitiveValues()?.AsList(); } }, + { "version", n => { Version = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfPrimitiveValues("ext", Ext); + writer.WriteObjectValue("meta", Meta); + writer.WriteCollectionOfPrimitiveValues("profile", Profile); + writer.WriteStringValue("version", Version); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/Meta.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/Meta.cs new file mode 100644 index 0000000000..4829eeb5a5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/Meta.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class Meta : IAdditionalDataHolder, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + public IDictionary AdditionalData + { + get { return BackingStore.Get>("AdditionalData") ?? new Dictionary(); } + set { BackingStore.Set("AdditionalData", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// + /// Instantiates a new and sets the default values. + /// + public Meta() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + AdditionalData = new Dictionary(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteAdditionalData(AdditionalData); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/NullableToOneTeacherInRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/NullableToOneTeacherInRequest.cs new file mode 100644 index 0000000000..3b65be2940 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/NullableToOneTeacherInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NullableToOneTeacherInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherIdentifierInRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NullableToOneTeacherInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.NullableToOneTeacherInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.NullableToOneTeacherInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherIdentifierInRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/NullableToOneTeacherInResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/NullableToOneTeacherInResponse.cs new file mode 100644 index 0000000000..ef6d9a9cdd --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/NullableToOneTeacherInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NullableToOneTeacherInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NullableToOneTeacherInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.NullableToOneTeacherInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.NullableToOneTeacherInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/OperationsRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/OperationsRequestDocument.cs new file mode 100644 index 0000000000..a61ba35865 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/OperationsRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class OperationsRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// The atomicOperations property + public List? AtomicOperations + { + get { return BackingStore?.Get?>("atomic:operations"); } + set { BackingStore?.Set("atomic:operations", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public OperationsRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.OperationsRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.OperationsRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "atomic:operations", n => { AtomicOperations = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("atomic:operations", AtomicOperations); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/OperationsResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/OperationsResponseDocument.cs new file mode 100644 index 0000000000..a9b1eef86c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/OperationsResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class OperationsResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// The atomicResults property + public List? AtomicResults + { + get { return BackingStore?.Get?>("atomic:results"); } + set { BackingStore?.Set("atomic:results", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The jsonapi property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Jsonapi? Jsonapi + { + get { return BackingStore?.Get("jsonapi"); } + set { BackingStore?.Set("jsonapi", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public OperationsResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.OperationsResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.OperationsResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "atomic:results", n => { AtomicResults = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicResult.CreateFromDiscriminatorValue)?.AsList(); } }, + { "jsonapi", n => { Jsonapi = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Jsonapi.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("atomic:results", AtomicResults); + writer.WriteObjectValue("jsonapi", Jsonapi); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipLinks.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipLinks.cs new file mode 100644 index 0000000000..a0d2ce3d38 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInCourseResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInCourseResponse.cs new file mode 100644 index 0000000000..c379e758f8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInCourseResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCourseResponse : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// The enrollments property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyEnrollmentInResponse? Enrollments + { + get { return BackingStore?.Get("enrollments"); } + set { BackingStore?.Set("enrollments", value); } + } + + /// The taughtBy property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyTeacherInResponse? TaughtBy + { + get { return BackingStore?.Get("taughtBy"); } + set { BackingStore?.Set("taughtBy", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCourseResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCourseResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "enrollments", n => { Enrollments = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyEnrollmentInResponse.CreateFromDiscriminatorValue); } }, + { "taughtBy", n => { TaughtBy = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyTeacherInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("enrollments", Enrollments); + writer.WriteObjectValue("taughtBy", TaughtBy); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInCreateCourseRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInCreateCourseRequest.cs new file mode 100644 index 0000000000..3e359c582b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInCreateCourseRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateCourseRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The enrollments property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyEnrollmentInRequest? Enrollments + { + get { return BackingStore?.Get("enrollments"); } + set { BackingStore?.Set("enrollments", value); } + } + + /// The taughtBy property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyTeacherInRequest? TaughtBy + { + get { return BackingStore?.Get("taughtBy"); } + set { BackingStore?.Set("taughtBy", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateCourseRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateCourseRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "enrollments", n => { Enrollments = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyEnrollmentInRequest.CreateFromDiscriminatorValue); } }, + { "taughtBy", n => { TaughtBy = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyTeacherInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("enrollments", Enrollments); + writer.WriteObjectValue("taughtBy", TaughtBy); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInCreateEnrollmentRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInCreateEnrollmentRequest.cs new file mode 100644 index 0000000000..fbbe4cd5fa --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInCreateEnrollmentRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateEnrollmentRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The course property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToOneCourseInRequest? Course + { + get { return BackingStore?.Get("course"); } + set { BackingStore?.Set("course", value); } + } + + /// The student property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToOneStudentInRequest? Student + { + get { return BackingStore?.Get("student"); } + set { BackingStore?.Set("student", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateEnrollmentRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateEnrollmentRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "course", n => { Course = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToOneCourseInRequest.CreateFromDiscriminatorValue); } }, + { "student", n => { Student = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToOneStudentInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("course", Course); + writer.WriteObjectValue("student", Student); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInCreateRequest.cs new file mode 100644 index 0000000000..2495275ea0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInCreateRequest.cs @@ -0,0 +1,78 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "courses" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateCourseRequest(), + "enrollments" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateEnrollmentRequest(), + "students" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateStudentRequest(), + "teachers" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateTeacherRequest(), + _ => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInCreateStudentRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInCreateStudentRequest.cs new file mode 100644 index 0000000000..ce58511fb7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInCreateStudentRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateStudentRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The enrollments property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyEnrollmentInRequest? Enrollments + { + get { return BackingStore?.Get("enrollments"); } + set { BackingStore?.Set("enrollments", value); } + } + + /// The mentor property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.NullableToOneTeacherInRequest? Mentor + { + get { return BackingStore?.Get("mentor"); } + set { BackingStore?.Set("mentor", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateStudentRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateStudentRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "enrollments", n => { Enrollments = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyEnrollmentInRequest.CreateFromDiscriminatorValue); } }, + { "mentor", n => { Mentor = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.NullableToOneTeacherInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("enrollments", Enrollments); + writer.WriteObjectValue("mentor", Mentor); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInCreateTeacherRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInCreateTeacherRequest.cs new file mode 100644 index 0000000000..4571924fb8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInCreateTeacherRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateTeacherRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The mentors property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyStudentInRequest? Mentors + { + get { return BackingStore?.Get("mentors"); } + set { BackingStore?.Set("mentors", value); } + } + + /// The teaches property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyCourseInRequest? Teaches + { + get { return BackingStore?.Get("teaches"); } + set { BackingStore?.Set("teaches", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateTeacherRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCreateTeacherRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "mentors", n => { Mentors = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyStudentInRequest.CreateFromDiscriminatorValue); } }, + { "teaches", n => { Teaches = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyCourseInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("mentors", Mentors); + writer.WriteObjectValue("teaches", Teaches); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInEnrollmentResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInEnrollmentResponse.cs new file mode 100644 index 0000000000..4de0b551e2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInEnrollmentResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInEnrollmentResponse : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// The course property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToOneCourseInResponse? Course + { + get { return BackingStore?.Get("course"); } + set { BackingStore?.Set("course", value); } + } + + /// The student property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToOneStudentInResponse? Student + { + get { return BackingStore?.Get("student"); } + set { BackingStore?.Set("student", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInEnrollmentResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInEnrollmentResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "course", n => { Course = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToOneCourseInResponse.CreateFromDiscriminatorValue); } }, + { "student", n => { Student = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToOneStudentInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("course", Course); + writer.WriteObjectValue("student", Student); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInResponse.cs new file mode 100644 index 0000000000..6902dedf96 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInResponse.cs @@ -0,0 +1,78 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "courses" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInCourseResponse(), + "enrollments" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInEnrollmentResponse(), + "students" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInStudentResponse(), + "teachers" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInTeacherResponse(), + _ => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInStudentResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInStudentResponse.cs new file mode 100644 index 0000000000..fe1560af47 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInStudentResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInStudentResponse : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// The enrollments property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyEnrollmentInResponse? Enrollments + { + get { return BackingStore?.Get("enrollments"); } + set { BackingStore?.Set("enrollments", value); } + } + + /// The mentor property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.NullableToOneTeacherInResponse? Mentor + { + get { return BackingStore?.Get("mentor"); } + set { BackingStore?.Set("mentor", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInStudentResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInStudentResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "enrollments", n => { Enrollments = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyEnrollmentInResponse.CreateFromDiscriminatorValue); } }, + { "mentor", n => { Mentor = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.NullableToOneTeacherInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("enrollments", Enrollments); + writer.WriteObjectValue("mentor", Mentor); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInTeacherResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInTeacherResponse.cs new file mode 100644 index 0000000000..aa2a9666db --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInTeacherResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInTeacherResponse : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// The mentors property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyStudentInResponse? Mentors + { + get { return BackingStore?.Get("mentors"); } + set { BackingStore?.Set("mentors", value); } + } + + /// The teaches property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyCourseInResponse? Teaches + { + get { return BackingStore?.Get("teaches"); } + set { BackingStore?.Set("teaches", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInTeacherResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInTeacherResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "mentors", n => { Mentors = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyStudentInResponse.CreateFromDiscriminatorValue); } }, + { "teaches", n => { Teaches = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyCourseInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("mentors", Mentors); + writer.WriteObjectValue("teaches", Teaches); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInUpdateCourseRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInUpdateCourseRequest.cs new file mode 100644 index 0000000000..fcec16798b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInUpdateCourseRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateCourseRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The enrollments property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyEnrollmentInRequest? Enrollments + { + get { return BackingStore?.Get("enrollments"); } + set { BackingStore?.Set("enrollments", value); } + } + + /// The taughtBy property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyTeacherInRequest? TaughtBy + { + get { return BackingStore?.Get("taughtBy"); } + set { BackingStore?.Set("taughtBy", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateCourseRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateCourseRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "enrollments", n => { Enrollments = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyEnrollmentInRequest.CreateFromDiscriminatorValue); } }, + { "taughtBy", n => { TaughtBy = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyTeacherInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("enrollments", Enrollments); + writer.WriteObjectValue("taughtBy", TaughtBy); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInUpdateEnrollmentRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInUpdateEnrollmentRequest.cs new file mode 100644 index 0000000000..4902edd159 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInUpdateEnrollmentRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateEnrollmentRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The course property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToOneCourseInRequest? Course + { + get { return BackingStore?.Get("course"); } + set { BackingStore?.Set("course", value); } + } + + /// The student property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToOneStudentInRequest? Student + { + get { return BackingStore?.Get("student"); } + set { BackingStore?.Set("student", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateEnrollmentRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateEnrollmentRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "course", n => { Course = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToOneCourseInRequest.CreateFromDiscriminatorValue); } }, + { "student", n => { Student = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToOneStudentInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("course", Course); + writer.WriteObjectValue("student", Student); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInUpdateRequest.cs new file mode 100644 index 0000000000..72224b3a16 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInUpdateRequest.cs @@ -0,0 +1,78 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "courses" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateCourseRequest(), + "enrollments" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateEnrollmentRequest(), + "students" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateStudentRequest(), + "teachers" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateTeacherRequest(), + _ => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInUpdateStudentRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInUpdateStudentRequest.cs new file mode 100644 index 0000000000..b2b4fde160 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInUpdateStudentRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateStudentRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The enrollments property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyEnrollmentInRequest? Enrollments + { + get { return BackingStore?.Get("enrollments"); } + set { BackingStore?.Set("enrollments", value); } + } + + /// The mentor property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.NullableToOneTeacherInRequest? Mentor + { + get { return BackingStore?.Get("mentor"); } + set { BackingStore?.Set("mentor", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateStudentRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateStudentRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "enrollments", n => { Enrollments = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyEnrollmentInRequest.CreateFromDiscriminatorValue); } }, + { "mentor", n => { Mentor = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.NullableToOneTeacherInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("enrollments", Enrollments); + writer.WriteObjectValue("mentor", Mentor); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInUpdateTeacherRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInUpdateTeacherRequest.cs new file mode 100644 index 0000000000..a2e503c4ca --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RelationshipsInUpdateTeacherRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateTeacherRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The mentors property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyStudentInRequest? Mentors + { + get { return BackingStore?.Get("mentors"); } + set { BackingStore?.Set("mentors", value); } + } + + /// The teaches property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyCourseInRequest? Teaches + { + get { return BackingStore?.Get("teaches"); } + set { BackingStore?.Set("teaches", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateTeacherRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipsInUpdateTeacherRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "mentors", n => { Mentors = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyStudentInRequest.CreateFromDiscriminatorValue); } }, + { "teaches", n => { Teaches = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyCourseInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("mentors", Mentors); + writer.WriteObjectValue("teaches", Teaches); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RemoveFromStudentEnrollmentsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RemoveFromStudentEnrollmentsRelationshipOperation.cs new file mode 100644 index 0000000000..b4f14e619f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RemoveFromStudentEnrollmentsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RemoveFromStudentEnrollmentsRelationshipOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RemoveOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentEnrollmentsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RemoveFromStudentEnrollmentsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RemoveFromStudentEnrollmentsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentEnrollmentsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RemoveFromTeacherMentorsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RemoveFromTeacherMentorsRelationshipOperation.cs new file mode 100644 index 0000000000..0d866c35ad --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RemoveFromTeacherMentorsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RemoveFromTeacherMentorsRelationshipOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RemoveOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherMentorsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RemoveFromTeacherMentorsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RemoveFromTeacherMentorsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherMentorsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RemoveFromTeacherTeachesRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RemoveFromTeacherTeachesRelationshipOperation.cs new file mode 100644 index 0000000000..7f645cf583 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RemoveFromTeacherTeachesRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RemoveFromTeacherTeachesRelationshipOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RemoveOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherTeachesRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RemoveFromTeacherTeachesRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RemoveFromTeacherTeachesRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherTeachesRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RemoveOperationCode.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RemoveOperationCode.cs new file mode 100644 index 0000000000..adce14d4ce --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/RemoveOperationCode.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum RemoveOperationCode + #pragma warning restore CS1591 + { + [EnumMember(Value = "remove")] + #pragma warning disable CS1591 + Remove, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ResourceInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ResourceInCreateRequest.cs new file mode 100644 index 0000000000..5ac8dbd672 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ResourceInCreateRequest.cs @@ -0,0 +1,87 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "courses" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInCreateCourseRequest(), + "enrollments" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInCreateEnrollmentRequest(), + "students" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInCreateStudentRequest(), + "teachers" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInCreateTeacherRequest(), + _ => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ResourceInResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ResourceInResponse.cs new file mode 100644 index 0000000000..770c825f12 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ResourceInResponse.cs @@ -0,0 +1,87 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "courses" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInCourseResponse(), + "enrollments" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInEnrollmentResponse(), + "students" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInStudentResponse(), + "teachers" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInTeacherResponse(), + _ => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ResourceInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ResourceInUpdateRequest.cs new file mode 100644 index 0000000000..bf38a35f4c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ResourceInUpdateRequest.cs @@ -0,0 +1,87 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "courses" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInUpdateCourseRequest(), + "enrollments" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInUpdateEnrollmentRequest(), + "students" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInUpdateStudentRequest(), + "teachers" => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInUpdateTeacherRequest(), + _ => new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ResourceLinks.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ResourceLinks.cs new file mode 100644 index 0000000000..4aead01fdf --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ResourceLinks.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ResourceTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ResourceTopLevelLinks.cs new file mode 100644 index 0000000000..c3ed8dfdb3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ResourceTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ResourceTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ResourceType.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ResourceType.cs new file mode 100644 index 0000000000..f1b11f5e63 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ResourceType.cs @@ -0,0 +1,30 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum ResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "courses")] + #pragma warning disable CS1591 + Courses, + #pragma warning restore CS1591 + [EnumMember(Value = "enrollments")] + #pragma warning disable CS1591 + Enrollments, + #pragma warning restore CS1591 + [EnumMember(Value = "students")] + #pragma warning disable CS1591 + Students, + #pragma warning restore CS1591 + [EnumMember(Value = "teachers")] + #pragma warning disable CS1591 + Teachers, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/StudentEnrollmentsRelationshipIdentifier.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/StudentEnrollmentsRelationshipIdentifier.cs new file mode 100644 index 0000000000..823b2baf07 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/StudentEnrollmentsRelationshipIdentifier.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class StudentEnrollmentsRelationshipIdentifier : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationship property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentEnrollmentsRelationshipName? Relationship + { + get { return BackingStore?.Get("relationship"); } + set { BackingStore?.Set("relationship", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public StudentEnrollmentsRelationshipIdentifier() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentEnrollmentsRelationshipIdentifier CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentEnrollmentsRelationshipIdentifier(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationship", n => { Relationship = n.GetEnumValue(); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteEnumValue("relationship", Relationship); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/StudentEnrollmentsRelationshipName.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/StudentEnrollmentsRelationshipName.cs new file mode 100644 index 0000000000..7ee5616951 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/StudentEnrollmentsRelationshipName.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum StudentEnrollmentsRelationshipName + #pragma warning restore CS1591 + { + [EnumMember(Value = "enrollments")] + #pragma warning disable CS1591 + Enrollments, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/StudentIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/StudentIdentifierInRequest.cs new file mode 100644 index 0000000000..ca44dd2749 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/StudentIdentifierInRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class StudentIdentifierInRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/StudentIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/StudentIdentifierInResponse.cs new file mode 100644 index 0000000000..be1224ea4d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/StudentIdentifierInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class StudentIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public StudentIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/StudentMentorRelationshipIdentifier.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/StudentMentorRelationshipIdentifier.cs new file mode 100644 index 0000000000..914e2f3eed --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/StudentMentorRelationshipIdentifier.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class StudentMentorRelationshipIdentifier : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationship property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentMentorRelationshipName? Relationship + { + get { return BackingStore?.Get("relationship"); } + set { BackingStore?.Set("relationship", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public StudentMentorRelationshipIdentifier() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentMentorRelationshipIdentifier CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentMentorRelationshipIdentifier(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationship", n => { Relationship = n.GetEnumValue(); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteEnumValue("relationship", Relationship); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/StudentMentorRelationshipName.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/StudentMentorRelationshipName.cs new file mode 100644 index 0000000000..d944176dab --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/StudentMentorRelationshipName.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum StudentMentorRelationshipName + #pragma warning restore CS1591 + { + [EnumMember(Value = "mentor")] + #pragma warning disable CS1591 + Mentor, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/StudentResourceType.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/StudentResourceType.cs new file mode 100644 index 0000000000..1f918135c8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/StudentResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum StudentResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "students")] + #pragma warning disable CS1591 + Students, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/TeacherIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/TeacherIdentifierInRequest.cs new file mode 100644 index 0000000000..04be63b9a9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/TeacherIdentifierInRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class TeacherIdentifierInRequest : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/TeacherIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/TeacherIdentifierInResponse.cs new file mode 100644 index 0000000000..dceef67fe8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/TeacherIdentifierInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class TeacherIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public TeacherIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/TeacherMentorsRelationshipIdentifier.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/TeacherMentorsRelationshipIdentifier.cs new file mode 100644 index 0000000000..3bd3c63ac1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/TeacherMentorsRelationshipIdentifier.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class TeacherMentorsRelationshipIdentifier : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationship property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherMentorsRelationshipName? Relationship + { + get { return BackingStore?.Get("relationship"); } + set { BackingStore?.Set("relationship", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public TeacherMentorsRelationshipIdentifier() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherMentorsRelationshipIdentifier CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherMentorsRelationshipIdentifier(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationship", n => { Relationship = n.GetEnumValue(); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteEnumValue("relationship", Relationship); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/TeacherMentorsRelationshipName.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/TeacherMentorsRelationshipName.cs new file mode 100644 index 0000000000..c38fd9dcbd --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/TeacherMentorsRelationshipName.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum TeacherMentorsRelationshipName + #pragma warning restore CS1591 + { + [EnumMember(Value = "mentors")] + #pragma warning disable CS1591 + Mentors, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/TeacherResourceType.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/TeacherResourceType.cs new file mode 100644 index 0000000000..71268c8d92 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/TeacherResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum TeacherResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "teachers")] + #pragma warning disable CS1591 + Teachers, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/TeacherTeachesRelationshipIdentifier.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/TeacherTeachesRelationshipIdentifier.cs new file mode 100644 index 0000000000..baa6632ac0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/TeacherTeachesRelationshipIdentifier.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class TeacherTeachesRelationshipIdentifier : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationship property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherTeachesRelationshipName? Relationship + { + get { return BackingStore?.Get("relationship"); } + set { BackingStore?.Set("relationship", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public TeacherTeachesRelationshipIdentifier() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherTeachesRelationshipIdentifier CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherTeachesRelationshipIdentifier(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationship", n => { Relationship = n.GetEnumValue(); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteEnumValue("relationship", Relationship); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/TeacherTeachesRelationshipName.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/TeacherTeachesRelationshipName.cs new file mode 100644 index 0000000000..29bc97b81e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/TeacherTeachesRelationshipName.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum TeacherTeachesRelationshipName + #pragma warning restore CS1591 + { + [EnumMember(Value = "teaches")] + #pragma warning disable CS1591 + Teaches, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyCourseInRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyCourseInRequest.cs new file mode 100644 index 0000000000..69679e4bbe --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyCourseInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyCourseInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyCourseInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyCourseInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyCourseInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyCourseInResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyCourseInResponse.cs new file mode 100644 index 0000000000..bf13a03b2b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyCourseInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyCourseInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyCourseInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyCourseInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyCourseInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyEnrollmentInRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyEnrollmentInRequest.cs new file mode 100644 index 0000000000..83d746d704 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyEnrollmentInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyEnrollmentInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyEnrollmentInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyEnrollmentInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyEnrollmentInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyEnrollmentInResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyEnrollmentInResponse.cs new file mode 100644 index 0000000000..28307d2486 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyEnrollmentInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyEnrollmentInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyEnrollmentInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyEnrollmentInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyEnrollmentInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyStudentInRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyStudentInRequest.cs new file mode 100644 index 0000000000..2fc8bbb3a1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyStudentInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyStudentInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyStudentInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyStudentInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyStudentInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyStudentInResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyStudentInResponse.cs new file mode 100644 index 0000000000..b73621fb3c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyStudentInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyStudentInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyStudentInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyStudentInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyStudentInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyTeacherInRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyTeacherInRequest.cs new file mode 100644 index 0000000000..6b2fc5e5a1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyTeacherInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyTeacherInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyTeacherInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyTeacherInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyTeacherInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyTeacherInResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyTeacherInResponse.cs new file mode 100644 index 0000000000..33053d4b3c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToManyTeacherInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyTeacherInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyTeacherInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyTeacherInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToManyTeacherInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToOneCourseInRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToOneCourseInRequest.cs new file mode 100644 index 0000000000..daf757b4e8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToOneCourseInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToOneCourseInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseIdentifierInRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToOneCourseInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToOneCourseInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToOneCourseInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseIdentifierInRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToOneCourseInResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToOneCourseInResponse.cs new file mode 100644 index 0000000000..534a18ec45 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToOneCourseInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToOneCourseInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToOneCourseInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToOneCourseInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToOneCourseInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToOneStudentInRequest.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToOneStudentInRequest.cs new file mode 100644 index 0000000000..b15e0172cd --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToOneStudentInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToOneStudentInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentIdentifierInRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToOneStudentInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToOneStudentInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToOneStudentInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentIdentifierInRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToOneStudentInResponse.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToOneStudentInResponse.cs new file mode 100644 index 0000000000..84132992cd --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/ToOneStudentInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToOneStudentInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToOneStudentInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToOneStudentInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ToOneStudentInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateCourseEnrollmentsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateCourseEnrollmentsRelationshipOperation.cs new file mode 100644 index 0000000000..72b9383be9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateCourseEnrollmentsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateCourseEnrollmentsRelationshipOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseEnrollmentsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateCourseEnrollmentsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateCourseEnrollmentsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseEnrollmentsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateCourseOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateCourseOperation.cs new file mode 100644 index 0000000000..58d63499a4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateCourseOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateCourseOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInUpdateCourseRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseIdentifierInRequest? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateCourseOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateCourseOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInUpdateCourseRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseIdentifierInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateEnrollmentCourseRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateEnrollmentCourseRelationshipOperation.cs new file mode 100644 index 0000000000..5e44dc1f5e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateEnrollmentCourseRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateEnrollmentCourseRelationshipOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseIdentifierInRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentCourseRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateEnrollmentCourseRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateEnrollmentCourseRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseIdentifierInRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentCourseRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateEnrollmentOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateEnrollmentOperation.cs new file mode 100644 index 0000000000..f814569a20 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateEnrollmentOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateEnrollmentOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInUpdateEnrollmentRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentIdentifierInRequest? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateEnrollmentOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateEnrollmentOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInUpdateEnrollmentRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentIdentifierInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateEnrollmentStudentRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateEnrollmentStudentRelationshipOperation.cs new file mode 100644 index 0000000000..363e0e09d5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateEnrollmentStudentRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateEnrollmentStudentRelationshipOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentIdentifierInRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentStudentRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateEnrollmentStudentRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateEnrollmentStudentRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentIdentifierInRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentStudentRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateOperationCode.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateOperationCode.cs new file mode 100644 index 0000000000..fda09b4cd2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateOperationCode.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum UpdateOperationCode + #pragma warning restore CS1591 + { + [EnumMember(Value = "update")] + #pragma warning disable CS1591 + Update, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateStudentEnrollmentsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateStudentEnrollmentsRelationshipOperation.cs new file mode 100644 index 0000000000..9eb0022467 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateStudentEnrollmentsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateStudentEnrollmentsRelationshipOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentEnrollmentsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateStudentEnrollmentsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateStudentEnrollmentsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.EnrollmentIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentEnrollmentsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateStudentMentorRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateStudentMentorRelationshipOperation.cs new file mode 100644 index 0000000000..a761aef583 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateStudentMentorRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateStudentMentorRelationshipOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherIdentifierInRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentMentorRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateStudentMentorRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateStudentMentorRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherIdentifierInRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentMentorRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateStudentOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateStudentOperation.cs new file mode 100644 index 0000000000..c076f9c709 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateStudentOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateStudentOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInUpdateStudentRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentIdentifierInRequest? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateStudentOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateStudentOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInUpdateStudentRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentIdentifierInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateTeacherMentorsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateTeacherMentorsRelationshipOperation.cs new file mode 100644 index 0000000000..775b95205f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateTeacherMentorsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateTeacherMentorsRelationshipOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherMentorsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateTeacherMentorsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateTeacherMentorsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.StudentIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherMentorsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateTeacherOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateTeacherOperation.cs new file mode 100644 index 0000000000..000f450288 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateTeacherOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateTeacherOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInUpdateTeacherRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherIdentifierInRequest? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateTeacherOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateTeacherOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.DataInUpdateTeacherRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherIdentifierInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateTeacherTeachesRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateTeacherTeachesRelationshipOperation.cs new file mode 100644 index 0000000000..5fc1ed4951 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Models/UpdateTeacherTeachesRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateTeacherTeachesRelationshipOperation : global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherTeachesRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateTeacherTeachesRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.UpdateTeacherTeachesRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.CourseIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.TeacherTeachesRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Operations/OperationsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Operations/OperationsRequestBuilder.cs new file mode 100644 index 0000000000..7ba9ad8e64 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/Operations/OperationsRequestBuilder.cs @@ -0,0 +1,94 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Operations +{ + /// + /// Builds and executes requests for operations under \operations + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OperationsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public OperationsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/operations", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public OperationsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/operations", rawUrl) + { + } + + /// + /// Performs multiple mutations in a linear and atomic manner. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.OperationsRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.OperationsResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Performs multiple mutations in a linear and atomic manner. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Models.OperationsRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=atomic;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=atomic;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Operations.OperationsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode.Operations.OperationsRequestBuilder(rawUrl, RequestAdapter); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/ClientIdGenerationModesTests.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/ClientIdGenerationModesTests.cs new file mode 100644 index 0000000000..d22e9e8cc2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/ClientIdGenerationModesTests.cs @@ -0,0 +1,273 @@ +using System.Net; +using FluentAssertions; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode; +using OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.ClientIdGenerationModes; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes; + +public sealed class ClientIdGenerationModesTests + : IClassFixture, ClientIdGenerationDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, ClientIdGenerationDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly ClientIdGenerationFakers _fakers = new(); + + public ClientIdGenerationModesTests(IntegrationTestContext, ClientIdGenerationDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + } + + [Fact] + public async Task Cannot_create_resource_without_ID_when_supplying_ID_is_required() + { + // Arrange + Player newPlayer = _fakers.Player.GenerateOne(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + ClientIdGenerationModesClient apiClient = new(requestAdapter); + + var requestBody = new CreatePlayerRequestDocument + { + Data = new DataInCreatePlayerRequest + { + Type = ResourceType.Players, + Attributes = new AttributesInCreatePlayerRequest + { + UserName = newPlayer.UserName + } + } + }; + + // Act + Func action = async () => _ = await apiClient.Players.PostAsync(requestBody); + + // Assert + ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync()).Which; + exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.UnprocessableEntity); + exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown."); + exception.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Errors[0]; + error.Status.Should().Be("422"); + error.Title.Should().Be("Failed to deserialize request body: The 'id' element is required."); + error.Detail.Should().BeNull(); + error.Source.Should().NotBeNull(); + error.Source.Pointer.Should().Be("/data"); + } + + [Fact] + public async Task Can_create_resource_with_ID_when_supplying_ID_is_required() + { + // Arrange + Player newPlayer = _fakers.Player.GenerateOne(); + newPlayer.Id = Guid.NewGuid(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + ClientIdGenerationModesClient apiClient = new(requestAdapter); + + var requestBody = new CreatePlayerRequestDocument + { + Data = new DataInCreatePlayerRequest + { + Type = ResourceType.Players, + Id = newPlayer.Id, + Attributes = new AttributesInCreatePlayerRequest + { + UserName = newPlayer.UserName + } + } + }; + + // Act + PrimaryPlayerResponseDocument? response = await apiClient.Players.PostAsync(requestBody); + + // Assert + response.Should().BeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Player playerInDatabase = await dbContext.Players.FirstWithIdAsync(newPlayer.Id); + + playerInDatabase.UserName.Should().Be(newPlayer.UserName); + }); + } + + [Fact] + public async Task Can_create_resource_without_ID_when_supplying_ID_is_allowed() + { + // Arrange + Game newGame = _fakers.Game.GenerateOne(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + ClientIdGenerationModesClient apiClient = new(requestAdapter); + + var requestBody = new CreateGameRequestDocument + { + Data = new DataInCreateGameRequest + { + Type = ResourceType.Games, + Attributes = new AttributesInCreateGameRequest + { + Title = newGame.Title, + PurchasePrice = (double)newGame.PurchasePrice + } + } + }; + + // Act + PrimaryGameResponseDocument? response = await apiClient.Games.PostAsync(requestBody); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().NotBeNull(); + response.Data.Id.Should().NotBeNull(); + response.Data.Id.Value.Should().NotBe(Guid.Empty); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Game gameInDatabase = await dbContext.Games.FirstWithIdAsync(response.Data.Id.Value); + + gameInDatabase.Title.Should().Be(newGame.Title); + gameInDatabase.PurchasePrice.Should().Be(newGame.PurchasePrice); + }); + } + + [Fact] + public async Task Can_create_resource_with_ID_when_supplying_ID_is_allowed() + { + // Arrange + Game newGame = _fakers.Game.GenerateOne(); + newGame.Id = Guid.NewGuid(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + ClientIdGenerationModesClient apiClient = new(requestAdapter); + + var requestBody = new CreateGameRequestDocument + { + Data = new DataInCreateGameRequest + { + Type = ResourceType.Games, + Id = newGame.Id, + Attributes = new AttributesInCreateGameRequest + { + Title = newGame.Title, + PurchasePrice = (double)newGame.PurchasePrice + } + } + }; + + // Act + PrimaryGameResponseDocument? response = await apiClient.Games.PostAsync(requestBody); + + // Assert + response.Should().BeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Game gameInDatabase = await dbContext.Games.FirstWithIdAsync(newGame.Id); + + gameInDatabase.Title.Should().Be(newGame.Title); + gameInDatabase.PurchasePrice.Should().Be(newGame.PurchasePrice); + }); + } + + [Fact] + public async Task Cannot_create_resource_with_existing_ID_when_supplying_ID_is_allowed() + { + // Arrange + Game existingGame = _fakers.Game.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Games.Add(existingGame); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + ClientIdGenerationModesClient apiClient = new(requestAdapter); + + var requestBody = new CreateGameRequestDocument + { + Data = new DataInCreateGameRequest + { + Type = ResourceType.Games, + Id = existingGame.Id, + Attributes = new AttributesInCreateGameRequest + { + Title = existingGame.Title, + PurchasePrice = (double)existingGame.PurchasePrice + } + } + }; + + // Act + Func action = async () => _ = await apiClient.Games.PostAsync(requestBody); + + // Assert + ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync()).Which; + exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.Conflict); + exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown."); + exception.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Errors.ElementAt(0); + error.Status.Should().Be("409"); + error.Title.Should().Be("Another resource with the specified ID already exists."); + error.Detail.Should().Be($"Another resource of type 'games' with ID '{existingGame.StringId}' already exists."); + } + + [Fact] + public async Task Can_create_resource_without_ID_when_supplying_ID_is_forbidden() + { + // Arrange + PlayerGroup newPlayerGroup = _fakers.Group.GenerateOne(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + ClientIdGenerationModesClient apiClient = new(requestAdapter); + + var requestBody = new CreatePlayerGroupRequestDocument + { + Data = new DataInCreatePlayerGroupRequest + { + Type = ResourceType.PlayerGroups, + Attributes = new AttributesInCreatePlayerGroupRequest + { + Name = newPlayerGroup.Name + } + } + }; + + // Act + PrimaryPlayerGroupResponseDocument? response = await apiClient.PlayerGroups.PostAsync(requestBody); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().NotBeNull(); + response.Data.Id.Should().NotBeNullOrEmpty(); + + long newPlayerGroupId = long.Parse(response.Data.Id); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + PlayerGroup playerGroupInDatabase = await dbContext.PlayerGroups.FirstWithIdAsync(newPlayerGroupId); + + playerGroupInDatabase.Name.Should().Be(newPlayerGroup.Name); + }); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/ClientIdGenerationModesClient.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/ClientIdGenerationModesClient.cs new file mode 100644 index 0000000000..28acff595c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/ClientIdGenerationModesClient.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using Microsoft.Kiota.Serialization.Form; +using Microsoft.Kiota.Serialization.Json; +using Microsoft.Kiota.Serialization.Multipart; +using Microsoft.Kiota.Serialization.Text; +using OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Games; +using OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.PlayerGroups; +using OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Players; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode +{ + /// + /// The main entry point of the SDK, exposes the configuration and the fluent API. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ClientIdGenerationModesClient : BaseRequestBuilder + { + /// The games property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Games.GamesRequestBuilder Games + { + get => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Games.GamesRequestBuilder(PathParameters, RequestAdapter); + } + + /// The playerGroups property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.PlayerGroups.PlayerGroupsRequestBuilder PlayerGroups + { + get => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.PlayerGroups.PlayerGroupsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The players property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Players.PlayersRequestBuilder Players + { + get => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Players.PlayersRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The backing store to use for the models. + /// The request adapter to use to execute the requests. + public ClientIdGenerationModesClient(IRequestAdapter requestAdapter, IBackingStoreFactory backingStore = default) : base(requestAdapter, "{+baseurl}", new Dictionary()) + { + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + if (string.IsNullOrEmpty(RequestAdapter.BaseUrl)) + { + RequestAdapter.BaseUrl = "http://localhost"; + } + PathParameters.TryAdd("baseurl", RequestAdapter.BaseUrl); + RequestAdapter.EnableBackingStore(backingStore); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Games/GamesRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Games/GamesRequestBuilder.cs new file mode 100644 index 0000000000..9c43818ad9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Games/GamesRequestBuilder.cs @@ -0,0 +1,103 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Games +{ + /// + /// Builds and executes requests for operations under \games + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class GamesRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public GamesRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/games{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public GamesRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/games{?query*}", rawUrl) + { + } + + /// + /// Creates a new game. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.CreateGameRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PrimaryGameResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new game. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.CreateGameRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Games.GamesRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Games.GamesRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Creates a new game. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class GamesRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInCreateGameRequest.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInCreateGameRequest.cs new file mode 100644 index 0000000000..81b6dad5b4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInCreateGameRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateGameRequest : global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The purchasePrice property + public double? PurchasePrice + { + get { return BackingStore?.Get("purchasePrice"); } + set { BackingStore?.Set("purchasePrice", value); } + } + + /// The title property + public string? Title + { + get { return BackingStore?.Get("title"); } + set { BackingStore?.Set("title", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInCreateGameRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInCreateGameRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "purchasePrice", n => { PurchasePrice = n.GetDoubleValue(); } }, + { "title", n => { Title = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteDoubleValue("purchasePrice", PurchasePrice); + writer.WriteStringValue("title", Title); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInCreatePlayerGroupRequest.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInCreatePlayerGroupRequest.cs new file mode 100644 index 0000000000..a0890d42e0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInCreatePlayerGroupRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreatePlayerGroupRequest : global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInCreatePlayerGroupRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInCreatePlayerGroupRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInCreatePlayerRequest.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInCreatePlayerRequest.cs new file mode 100644 index 0000000000..0e08fbe104 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInCreatePlayerRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreatePlayerRequest : global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The userName property + public string? UserName + { + get { return BackingStore?.Get("userName"); } + set { BackingStore?.Set("userName", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInCreatePlayerRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInCreatePlayerRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "userName", n => { UserName = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("userName", UserName); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInCreateRequest.cs new file mode 100644 index 0000000000..5661aa5ced --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInCreateRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "games" => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInCreateGameRequest(), + "playerGroups" => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInCreatePlayerGroupRequest(), + "players" => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInCreatePlayerRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInGameResponse.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInGameResponse.cs new file mode 100644 index 0000000000..83699cbc7c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInGameResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInGameResponse : global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The purchasePrice property + public double? PurchasePrice + { + get { return BackingStore?.Get("purchasePrice"); } + set { BackingStore?.Set("purchasePrice", value); } + } + + /// The title property + public string? Title + { + get { return BackingStore?.Get("title"); } + set { BackingStore?.Set("title", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInGameResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInGameResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "purchasePrice", n => { PurchasePrice = n.GetDoubleValue(); } }, + { "title", n => { Title = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteDoubleValue("purchasePrice", PurchasePrice); + writer.WriteStringValue("title", Title); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInPlayerGroupResponse.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInPlayerGroupResponse.cs new file mode 100644 index 0000000000..07adaf6403 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInPlayerGroupResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInPlayerGroupResponse : global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInPlayerGroupResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInPlayerGroupResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInPlayerResponse.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInPlayerResponse.cs new file mode 100644 index 0000000000..e23122f9dd --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInPlayerResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInPlayerResponse : global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The userName property + public string? UserName + { + get { return BackingStore?.Get("userName"); } + set { BackingStore?.Set("userName", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInPlayerResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInPlayerResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "userName", n => { UserName = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("userName", UserName); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInResponse.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInResponse.cs new file mode 100644 index 0000000000..e56ce8d295 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/AttributesInResponse.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "games" => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInGameResponse(), + "playerGroups" => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInPlayerGroupResponse(), + "players" => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInPlayerResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/CreateGameRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/CreateGameRequestDocument.cs new file mode 100644 index 0000000000..e248697cda --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/CreateGameRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateGameRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInCreateGameRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateGameRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.CreateGameRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.CreateGameRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInCreateGameRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/CreatePlayerGroupRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/CreatePlayerGroupRequestDocument.cs new file mode 100644 index 0000000000..6625e35064 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/CreatePlayerGroupRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreatePlayerGroupRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInCreatePlayerGroupRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreatePlayerGroupRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.CreatePlayerGroupRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.CreatePlayerGroupRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInCreatePlayerGroupRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/CreatePlayerRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/CreatePlayerRequestDocument.cs new file mode 100644 index 0000000000..addd7b6224 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/CreatePlayerRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreatePlayerRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInCreatePlayerRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreatePlayerRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.CreatePlayerRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.CreatePlayerRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInCreatePlayerRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/DataInCreateGameRequest.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/DataInCreateGameRequest.cs new file mode 100644 index 0000000000..b9c39a55b6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/DataInCreateGameRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateGameRequest : global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInCreateGameRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInCreateGameRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInCreateGameRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInCreateGameRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetGuidValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteGuidValue("id", Id); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/DataInCreatePlayerGroupRequest.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/DataInCreatePlayerGroupRequest.cs new file mode 100644 index 0000000000..273cdc05f9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/DataInCreatePlayerGroupRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreatePlayerGroupRequest : global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInCreatePlayerGroupRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInCreatePlayerGroupRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInCreatePlayerGroupRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInCreatePlayerGroupRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInCreatePlayerGroupRequest.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInCreatePlayerGroupRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/DataInCreatePlayerRequest.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/DataInCreatePlayerRequest.cs new file mode 100644 index 0000000000..674f245d09 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/DataInCreatePlayerRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreatePlayerRequest : global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInCreatePlayerRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInCreatePlayerRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInCreatePlayerRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInCreatePlayerRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInCreatePlayerRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetGuidValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInCreatePlayerRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteGuidValue("id", Id); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/DataInGameResponse.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/DataInGameResponse.cs new file mode 100644 index 0000000000..f4dfd7903c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/DataInGameResponse.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInGameResponse : global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInGameResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInGameResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInGameResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInGameResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetGuidValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteGuidValue("id", Id); + writer.WriteObjectValue("links", Links); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/DataInPlayerGroupResponse.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/DataInPlayerGroupResponse.cs new file mode 100644 index 0000000000..4f340d6718 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/DataInPlayerGroupResponse.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInPlayerGroupResponse : global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInPlayerGroupResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInPlayerGroupResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInPlayerGroupResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInPlayerGroupResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInPlayerGroupResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInPlayerGroupResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/DataInPlayerResponse.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/DataInPlayerResponse.cs new file mode 100644 index 0000000000..cf01cc0cb9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/DataInPlayerResponse.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInPlayerResponse : global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInPlayerResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInPlayerResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInPlayerResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInPlayerResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.AttributesInPlayerResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetGuidValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInPlayerResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteGuidValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ErrorLinks.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ErrorLinks.cs new file mode 100644 index 0000000000..2f02de5cc3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ErrorLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// The about property + public string? About + { + get { return BackingStore?.Get("about"); } + set { BackingStore?.Set("about", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The type property + public string? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "about", n => { About = n.GetStringValue(); } }, + { "type", n => { Type = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("about", About); + writer.WriteStringValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ErrorObject.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ErrorObject.cs new file mode 100644 index 0000000000..3a4c7d8b81 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ErrorObject.cs @@ -0,0 +1,133 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorObject : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The code property + public string? Code + { + get { return BackingStore?.Get("code"); } + set { BackingStore?.Set("code", value); } + } + + /// The detail property + public string? Detail + { + get { return BackingStore?.Get("detail"); } + set { BackingStore?.Set("detail", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The source property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorSource? Source + { + get { return BackingStore?.Get("source"); } + set { BackingStore?.Set("source", value); } + } + + /// The status property + public string? Status + { + get { return BackingStore?.Get("status"); } + set { BackingStore?.Set("status", value); } + } + + /// The title property + public string? Title + { + get { return BackingStore?.Get("title"); } + set { BackingStore?.Set("title", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorObject() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorObject CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorObject(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "code", n => { Code = n.GetStringValue(); } }, + { "detail", n => { Detail = n.GetStringValue(); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "source", n => { Source = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorSource.CreateFromDiscriminatorValue); } }, + { "status", n => { Status = n.GetStringValue(); } }, + { "title", n => { Title = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("code", Code); + writer.WriteStringValue("detail", Detail); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + writer.WriteObjectValue("source", Source); + writer.WriteStringValue("status", Status); + writer.WriteStringValue("title", Title); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ErrorResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ErrorResponseDocument.cs new file mode 100644 index 0000000000..d241bf29b3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ErrorResponseDocument.cs @@ -0,0 +1,92 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorResponseDocument : ApiException, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The errors property + public List? Errors + { + get { return BackingStore?.Get?>("errors"); } + set { BackingStore?.Set("errors", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The primary error message. + public override string Message { get => base.Message; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "errors", n => { Errors = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorObject.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("errors", Errors); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ErrorSource.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ErrorSource.cs new file mode 100644 index 0000000000..ba320e7863 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ErrorSource.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorSource : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The header property + public string? Header + { + get { return BackingStore?.Get("header"); } + set { BackingStore?.Set("header", value); } + } + + /// The parameter property + public string? Parameter + { + get { return BackingStore?.Get("parameter"); } + set { BackingStore?.Set("parameter", value); } + } + + /// The pointer property + public string? Pointer + { + get { return BackingStore?.Get("pointer"); } + set { BackingStore?.Set("pointer", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorSource() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorSource CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorSource(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "header", n => { Header = n.GetStringValue(); } }, + { "parameter", n => { Parameter = n.GetStringValue(); } }, + { "pointer", n => { Pointer = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("header", Header); + writer.WriteStringValue("parameter", Parameter); + writer.WriteStringValue("pointer", Pointer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ErrorTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ErrorTopLevelLinks.cs new file mode 100644 index 0000000000..6248e2193b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ErrorTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/GameIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/GameIdentifierInRequest.cs new file mode 100644 index 0000000000..ebb12863b6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/GameIdentifierInRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class GameIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.GameIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.GameIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetGuidValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteGuidValue("id", Id); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/GameIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/GameIdentifierInResponse.cs new file mode 100644 index 0000000000..57894ff37c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/GameIdentifierInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class GameIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.GameResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public GameIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.GameIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.GameIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetGuidValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteGuidValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/GameResourceType.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/GameResourceType.cs new file mode 100644 index 0000000000..9b3cf95ac3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/GameResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum GameResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "games")] + #pragma warning disable CS1591 + Games, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/IdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/IdentifierInRequest.cs new file mode 100644 index 0000000000..da6c488aca --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/IdentifierInRequest.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class IdentifierInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public IdentifierInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.IdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "games" => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.GameIdentifierInRequest(), + "playerGroups" => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PlayerGroupIdentifierInRequest(), + "players" => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PlayerIdentifierInRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.IdentifierInRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/Meta.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/Meta.cs new file mode 100644 index 0000000000..ed1e881c84 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/Meta.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class Meta : IAdditionalDataHolder, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + public IDictionary AdditionalData + { + get { return BackingStore.Get>("AdditionalData") ?? new Dictionary(); } + set { BackingStore.Set("AdditionalData", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// + /// Instantiates a new and sets the default values. + /// + public Meta() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + AdditionalData = new Dictionary(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteAdditionalData(AdditionalData); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PlayerGroupIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PlayerGroupIdentifierInRequest.cs new file mode 100644 index 0000000000..ac6196074a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PlayerGroupIdentifierInRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PlayerGroupIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PlayerGroupIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PlayerGroupIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PlayerGroupIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PlayerGroupIdentifierInResponse.cs new file mode 100644 index 0000000000..f0ca1c3b46 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PlayerGroupIdentifierInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PlayerGroupIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PlayerGroupResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PlayerGroupIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PlayerGroupIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PlayerGroupIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PlayerGroupResourceType.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PlayerGroupResourceType.cs new file mode 100644 index 0000000000..b5f7d16eb5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PlayerGroupResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum PlayerGroupResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "playerGroups")] + #pragma warning disable CS1591 + PlayerGroups, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PlayerIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PlayerIdentifierInRequest.cs new file mode 100644 index 0000000000..ad41f6900e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PlayerIdentifierInRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PlayerIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PlayerIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PlayerIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetGuidValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteGuidValue("id", Id); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PlayerIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PlayerIdentifierInResponse.cs new file mode 100644 index 0000000000..ad0022f548 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PlayerIdentifierInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PlayerIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PlayerResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PlayerIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PlayerIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PlayerIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetGuidValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteGuidValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PlayerResourceType.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PlayerResourceType.cs new file mode 100644 index 0000000000..02f282b648 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PlayerResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum PlayerResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "players")] + #pragma warning disable CS1591 + Players, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PrimaryGameResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PrimaryGameResponseDocument.cs new file mode 100644 index 0000000000..eb87b15731 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PrimaryGameResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryGameResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInGameResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryGameResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PrimaryGameResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PrimaryGameResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInGameResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PrimaryPlayerGroupResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PrimaryPlayerGroupResponseDocument.cs new file mode 100644 index 0000000000..ebb52b48cd --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PrimaryPlayerGroupResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryPlayerGroupResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInPlayerGroupResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryPlayerGroupResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PrimaryPlayerGroupResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PrimaryPlayerGroupResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInPlayerGroupResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PrimaryPlayerResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PrimaryPlayerResponseDocument.cs new file mode 100644 index 0000000000..86ba7e7572 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/PrimaryPlayerResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryPlayerResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInPlayerResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryPlayerResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PrimaryPlayerResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PrimaryPlayerResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInPlayerResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/RelationshipLinks.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/RelationshipLinks.cs new file mode 100644 index 0000000000..5c5d1d84f9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/RelationshipLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/RelationshipsInCreatePlayerGroupRequest.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/RelationshipsInCreatePlayerGroupRequest.cs new file mode 100644 index 0000000000..ac7620c563 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/RelationshipsInCreatePlayerGroupRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreatePlayerGroupRequest : global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The players property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyPlayerInRequest? Players + { + get { return BackingStore?.Get("players"); } + set { BackingStore?.Set("players", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInCreatePlayerGroupRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInCreatePlayerGroupRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "players", n => { Players = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyPlayerInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("players", Players); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/RelationshipsInCreatePlayerRequest.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/RelationshipsInCreatePlayerRequest.cs new file mode 100644 index 0000000000..9ebc8c4db9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/RelationshipsInCreatePlayerRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreatePlayerRequest : global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The memberOf property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyPlayerGroupInRequest? MemberOf + { + get { return BackingStore?.Get("memberOf"); } + set { BackingStore?.Set("memberOf", value); } + } + + /// The ownedGames property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyGameInRequest? OwnedGames + { + get { return BackingStore?.Get("ownedGames"); } + set { BackingStore?.Set("ownedGames", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInCreatePlayerRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInCreatePlayerRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "memberOf", n => { MemberOf = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyPlayerGroupInRequest.CreateFromDiscriminatorValue); } }, + { "ownedGames", n => { OwnedGames = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyGameInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("memberOf", MemberOf); + writer.WriteObjectValue("ownedGames", OwnedGames); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/RelationshipsInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/RelationshipsInCreateRequest.cs new file mode 100644 index 0000000000..7be2a2fe20 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/RelationshipsInCreateRequest.cs @@ -0,0 +1,76 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "playerGroups" => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInCreatePlayerGroupRequest(), + "players" => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInCreatePlayerRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/RelationshipsInPlayerGroupResponse.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/RelationshipsInPlayerGroupResponse.cs new file mode 100644 index 0000000000..289181d405 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/RelationshipsInPlayerGroupResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInPlayerGroupResponse : global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// The players property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyPlayerInResponse? Players + { + get { return BackingStore?.Get("players"); } + set { BackingStore?.Set("players", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInPlayerGroupResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInPlayerGroupResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "players", n => { Players = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyPlayerInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("players", Players); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/RelationshipsInPlayerResponse.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/RelationshipsInPlayerResponse.cs new file mode 100644 index 0000000000..15bff75fb5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/RelationshipsInPlayerResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInPlayerResponse : global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// The memberOf property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyPlayerGroupInResponse? MemberOf + { + get { return BackingStore?.Get("memberOf"); } + set { BackingStore?.Set("memberOf", value); } + } + + /// The ownedGames property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyGameInResponse? OwnedGames + { + get { return BackingStore?.Get("ownedGames"); } + set { BackingStore?.Set("ownedGames", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInPlayerResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInPlayerResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "memberOf", n => { MemberOf = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyPlayerGroupInResponse.CreateFromDiscriminatorValue); } }, + { "ownedGames", n => { OwnedGames = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyGameInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("memberOf", MemberOf); + writer.WriteObjectValue("ownedGames", OwnedGames); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/RelationshipsInResponse.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/RelationshipsInResponse.cs new file mode 100644 index 0000000000..437b617413 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/RelationshipsInResponse.cs @@ -0,0 +1,76 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "playerGroups" => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInPlayerGroupResponse(), + "players" => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInPlayerResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipsInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ResourceInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ResourceInCreateRequest.cs new file mode 100644 index 0000000000..d088941ea4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ResourceInCreateRequest.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "games" => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInCreateGameRequest(), + "playerGroups" => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInCreatePlayerGroupRequest(), + "players" => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInCreatePlayerRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ResourceInResponse.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ResourceInResponse.cs new file mode 100644 index 0000000000..422dc8da2f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ResourceInResponse.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "games" => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInGameResponse(), + "playerGroups" => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInPlayerGroupResponse(), + "players" => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.DataInPlayerResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ResourceLinks.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ResourceLinks.cs new file mode 100644 index 0000000000..38baa2821d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ResourceLinks.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ResourceTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ResourceTopLevelLinks.cs new file mode 100644 index 0000000000..029aebb185 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ResourceTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ResourceTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ResourceType.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ResourceType.cs new file mode 100644 index 0000000000..85f3a3aaeb --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ResourceType.cs @@ -0,0 +1,26 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum ResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "games")] + #pragma warning disable CS1591 + Games, + #pragma warning restore CS1591 + [EnumMember(Value = "playerGroups")] + #pragma warning disable CS1591 + PlayerGroups, + #pragma warning restore CS1591 + [EnumMember(Value = "players")] + #pragma warning disable CS1591 + Players, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ToManyGameInRequest.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ToManyGameInRequest.cs new file mode 100644 index 0000000000..9e228a880a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ToManyGameInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyGameInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyGameInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyGameInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyGameInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.GameIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ToManyGameInResponse.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ToManyGameInResponse.cs new file mode 100644 index 0000000000..ddfc87aeed --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ToManyGameInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyGameInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyGameInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyGameInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyGameInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.GameIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ToManyPlayerGroupInRequest.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ToManyPlayerGroupInRequest.cs new file mode 100644 index 0000000000..cf529fb67e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ToManyPlayerGroupInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyPlayerGroupInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyPlayerGroupInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyPlayerGroupInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyPlayerGroupInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PlayerGroupIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ToManyPlayerGroupInResponse.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ToManyPlayerGroupInResponse.cs new file mode 100644 index 0000000000..67dafa1e59 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ToManyPlayerGroupInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyPlayerGroupInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyPlayerGroupInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyPlayerGroupInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyPlayerGroupInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PlayerGroupIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ToManyPlayerInRequest.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ToManyPlayerInRequest.cs new file mode 100644 index 0000000000..5c0824035b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ToManyPlayerInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyPlayerInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyPlayerInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyPlayerInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyPlayerInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PlayerIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ToManyPlayerInResponse.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ToManyPlayerInResponse.cs new file mode 100644 index 0000000000..4b17c25cc3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Models/ToManyPlayerInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyPlayerInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyPlayerInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyPlayerInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ToManyPlayerInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PlayerIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/PlayerGroups/PlayerGroupsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/PlayerGroups/PlayerGroupsRequestBuilder.cs new file mode 100644 index 0000000000..c7ba47a086 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/PlayerGroups/PlayerGroupsRequestBuilder.cs @@ -0,0 +1,105 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.PlayerGroups +{ + /// + /// Builds and executes requests for operations under \playerGroups + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class PlayerGroupsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public PlayerGroupsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/playerGroups{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public PlayerGroupsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/playerGroups{?query*}", rawUrl) + { + } + + /// + /// Creates a new playerGroup. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.CreatePlayerGroupRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PrimaryPlayerGroupResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new playerGroup. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.CreatePlayerGroupRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.PlayerGroups.PlayerGroupsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.PlayerGroups.PlayerGroupsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Creates a new playerGroup. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class PlayerGroupsRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Players/PlayersRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Players/PlayersRequestBuilder.cs new file mode 100644 index 0000000000..f88f040c6e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/Players/PlayersRequestBuilder.cs @@ -0,0 +1,103 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Players +{ + /// + /// Builds and executes requests for operations under \players + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class PlayersRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public PlayersRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/players{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public PlayersRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/players{?query*}", rawUrl) + { + } + + /// + /// Creates a new player. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.CreatePlayerRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.PrimaryPlayerResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new player. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models.CreatePlayerRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Players.PlayersRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Players.PlayersRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Creates a new player. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class PlayersRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/ETagTests.cs b/test/OpenApiKiotaEndToEndTests/Headers/ETagTests.cs new file mode 100644 index 0000000000..0020d1d174 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/ETagTests.cs @@ -0,0 +1,244 @@ +using System.Net; +using FluentAssertions; +using Microsoft.Kiota.Abstractions; +using Microsoft.Kiota.Http.HttpClientLibrary; +using Microsoft.Kiota.Http.HttpClientLibrary.Middleware.Options; +using Microsoft.Net.Http.Headers; +using OpenApiKiotaEndToEndTests.Headers.GeneratedCode; +using OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.Headers; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.Headers; + +public sealed class ETagTests : IClassFixture, HeaderDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, HeaderDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly HeaderFakers _fakers = new(); + + public ETagTests(IntegrationTestContext, HeaderDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseController(); + } + + [Fact] + public async Task Returns_ETag_for_HEAD_request() + { + // Arrange + List countries = _fakers.Country.GenerateList(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Countries.AddRange(countries); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new HeadersClient(requestAdapter); + + var headerInspector = new HeadersInspectionHandlerOption + { + InspectResponseHeaders = true + }; + + // Act + await apiClient.Countries.HeadAsync(configuration => configuration.Options.Add(headerInspector)); + + // Assert + string[] eTagHeaderValues = headerInspector.ResponseHeaders.Should().ContainKey(HeaderNames.ETag).WhoseValue.ToArray(); + eTagHeaderValues.Should().HaveCount(1); + eTagHeaderValues[0].Should().Match("\"*\""); + } + + [Fact] + public async Task Returns_ETag_for_GET_request() + { + // Arrange + List countries = _fakers.Country.GenerateList(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Countries.AddRange(countries); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new HeadersClient(requestAdapter); + + var headerInspector = new HeadersInspectionHandlerOption + { + InspectResponseHeaders = true + }; + + // Act + CountryCollectionResponseDocument? response = await apiClient.Countries.GetAsync(configuration => configuration.Options.Add(headerInspector)); + + // Assert + response.Should().NotBeNull(); + + string[] eTagHeaderValues = headerInspector.ResponseHeaders.Should().ContainKey(HeaderNames.ETag).WhoseValue.ToArray(); + eTagHeaderValues.Should().HaveCount(1); + eTagHeaderValues[0].Should().Match("\"*\""); + } + + [Fact] + public async Task Returns_no_ETag_for_failed_GET_request() + { + // Arrange + Guid unknownCountryId = Unknown.TypedId.Guid; + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new HeadersClient(requestAdapter); + + var headerInspector = new HeadersInspectionHandlerOption + { + InspectResponseHeaders = true + }; + + // Act + Func action = async () => await apiClient.Countries[unknownCountryId].GetAsync(configuration => configuration.Options.Add(headerInspector)); + + // Assert + ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync()).Which; + exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.NotFound); + exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown."); + exception.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Errors.ElementAt(0); + error.Status.Should().Be("404"); + error.Title.Should().Be("The requested resource does not exist."); + error.Detail.Should().Be($"Resource of type 'countries' with ID '{unknownCountryId}' does not exist."); + + headerInspector.ResponseHeaders.Should().NotContainKey(HeaderNames.ETag); + } + + [Fact] + public async Task Returns_no_ETag_for_POST_request() + { + // Arrange + Country newCountry = _fakers.Country.GenerateOne(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new HeadersClient(requestAdapter); + + var headerInspector = new HeadersInspectionHandlerOption + { + InspectResponseHeaders = true + }; + + var requestBody = new CreateCountryRequestDocument + { + Data = new DataInCreateCountryRequest + { + Type = ResourceType.Countries, + Attributes = new AttributesInCreateCountryRequest + { + Name = newCountry.Name, + Population = newCountry.Population + } + } + }; + + // Act + PrimaryCountryResponseDocument? response = + await apiClient.Countries.PostAsync(requestBody, configuration => configuration.Options.Add(headerInspector)); + + // Assert + response.Should().NotBeNull(); + + headerInspector.ResponseHeaders.Should().NotContainKey(HeaderNames.ETag); + } + + [Fact] + public async Task Returns_NotModified_for_matching_ETag() + { + // Arrange + List countries = _fakers.Country.GenerateList(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Countries.AddRange(countries); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new HeadersClient(requestAdapter); + + var headerInspector = new HeadersInspectionHandlerOption + { + InspectResponseHeaders = true + }; + + _ = await apiClient.Countries.GetAsync(configuration => configuration.Options.Add(headerInspector)); + + string responseETag = headerInspector.ResponseHeaders[HeaderNames.ETag].Single(); + headerInspector.ResponseHeaders.Clear(); + + // Act + Func action = async () => await apiClient.Countries.GetAsync(configuration => + { + configuration.Headers.Add(HeaderNames.IfNoneMatch, responseETag); + configuration.Options.Add(headerInspector); + }); + + // Assert + ApiException exception = (await action.Should().ThrowExactlyAsync()).Which; + exception.Message.Should().Be("The server returned an unexpected status code and no error factory is registered for this code: 304"); + exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.NotModified); + + string[] eTagHeaderValues = headerInspector.ResponseHeaders.Should().ContainKey(HeaderNames.ETag).WhoseValue.ToArray(); + eTagHeaderValues.Should().HaveCount(1); + eTagHeaderValues[0].Should().Be(responseETag); + } + + [Fact] + public async Task Returns_content_for_mismatching_ETag() + { + // Arrange + List countries = _fakers.Country.GenerateList(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Countries.AddRange(countries); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new HeadersClient(requestAdapter); + + var headerInspector = new HeadersInspectionHandlerOption + { + InspectResponseHeaders = true + }; + + // Act + CountryCollectionResponseDocument? response = await apiClient.Countries.GetAsync(configuration => + { + configuration.Headers.Add(HeaderNames.IfNoneMatch, "\"Not-a-matching-value\""); + configuration.Options.Add(headerInspector); + }); + + // Assert + response.Should().NotBeNull(); + + string[] eTagHeaderValues = headerInspector.ResponseHeaders.Should().ContainKey(HeaderNames.ETag).WhoseValue.ToArray(); + eTagHeaderValues.Should().HaveCount(1); + eTagHeaderValues[0].Should().Match("\"*\""); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Countries/CountriesRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Countries/CountriesRequestBuilder.cs new file mode 100644 index 0000000000..806b7443ab --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Countries/CountriesRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.Item; +using OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries +{ + /// + /// Builds and executes requests for operations under \countries + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class CountriesRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.Headers.GeneratedCode.countries.item collection + /// The identifier of the country to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.Item.CountriesItemRequestBuilder this[Guid position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.Item.CountriesItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public CountriesRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/countries{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public CountriesRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/countries{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of countries. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.CountryCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new country. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.CreateCountryRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.PrimaryCountryResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of countries. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new country. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.CreateCountryRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.CountriesRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.CountriesRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of countries. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class CountriesRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class CountriesRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new country. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class CountriesRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Countries/Item/CountriesItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Countries/Item/CountriesItemRequestBuilder.cs new file mode 100644 index 0000000000..7dc4b09903 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Countries/Item/CountriesItemRequestBuilder.cs @@ -0,0 +1,223 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.Item.Languages; +using OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.Item.Relationships; +using OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.Item +{ + /// + /// Builds and executes requests for operations under \countries\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class CountriesItemRequestBuilder : BaseRequestBuilder + { + /// The languages property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.Item.Languages.LanguagesRequestBuilder Languages + { + get => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.Item.Languages.LanguagesRequestBuilder(PathParameters, RequestAdapter); + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public CountriesItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/countries/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public CountriesItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/countries/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing country by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual country by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.PrimaryCountryResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing country. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.UpdateCountryRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.PrimaryCountryResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing country by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual country by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing country. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.UpdateCountryRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.Item.CountriesItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.Item.CountriesItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual country by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class CountriesItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class CountriesItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing country. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class CountriesItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Countries/Item/Languages/LanguagesRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Countries/Item/Languages/LanguagesRequestBuilder.cs new file mode 100644 index 0000000000..754319b921 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Countries/Item/Languages/LanguagesRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.Item.Languages +{ + /// + /// Builds and executes requests for operations under \countries\{id}\languages + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class LanguagesRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public LanguagesRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/countries/{id}/languages{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public LanguagesRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/countries/{id}/languages{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related languages of an individual country's languages relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.LanguageCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related languages of an individual country's languages relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.Item.Languages.LanguagesRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.Item.Languages.LanguagesRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related languages of an individual country's languages relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class LanguagesRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class LanguagesRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Countries/Item/Relationships/Languages/LanguagesRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Countries/Item/Relationships/Languages/LanguagesRequestBuilder.cs new file mode 100644 index 0000000000..b7c239dca4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Countries/Item/Relationships/Languages/LanguagesRequestBuilder.cs @@ -0,0 +1,248 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.Item.Relationships.Languages +{ + /// + /// Builds and executes requests for operations under \countries\{id}\relationships\languages + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class LanguagesRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public LanguagesRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/countries/{id}/relationships/languages{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public LanguagesRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/countries/{id}/relationships/languages{?query*}", rawUrl) + { + } + + /// + /// Removes existing languages from the languages relationship of an individual country. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task DeleteAsync(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ToManyLanguageInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToDeleteRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related language identities of an individual country's languages relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.LanguageIdentifierCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns existing languages to the languages relationship of an individual country. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ToManyLanguageInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Adds existing languages to the languages relationship of an individual country. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ToManyLanguageInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Removes existing languages from the languages relationship of an individual country. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ToManyLanguageInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Retrieves the related language identities of an individual country's languages relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns existing languages to the languages relationship of an individual country. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ToManyLanguageInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Adds existing languages to the languages relationship of an individual country. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ToManyLanguageInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.Item.Relationships.Languages.LanguagesRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.Item.Relationships.Languages.LanguagesRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related language identities of an individual country's languages relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class LanguagesRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class LanguagesRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Countries/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Countries/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..81d3e29f45 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Countries/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.Item.Relationships.Languages; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \countries\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The languages property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.Item.Relationships.Languages.LanguagesRequestBuilder Languages + { + get => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.Item.Relationships.Languages.LanguagesRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/countries/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/countries/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/HeadersClient.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/HeadersClient.cs new file mode 100644 index 0000000000..2d6d36e4cb --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/HeadersClient.cs @@ -0,0 +1,54 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using Microsoft.Kiota.Serialization.Form; +using Microsoft.Kiota.Serialization.Json; +using Microsoft.Kiota.Serialization.Multipart; +using Microsoft.Kiota.Serialization.Text; +using OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode +{ + /// + /// The main entry point of the SDK, exposes the configuration and the fluent API. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class HeadersClient : BaseRequestBuilder + { + /// The countries property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.CountriesRequestBuilder Countries + { + get => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Countries.CountriesRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The backing store to use for the models. + /// The request adapter to use to execute the requests. + public HeadersClient(IRequestAdapter requestAdapter, IBackingStoreFactory backingStore = default) : base(requestAdapter, "{+baseurl}", new Dictionary()) + { + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + if (string.IsNullOrEmpty(RequestAdapter.BaseUrl)) + { + RequestAdapter.BaseUrl = "http://localhost"; + } + PathParameters.TryAdd("baseurl", RequestAdapter.BaseUrl); + RequestAdapter.EnableBackingStore(backingStore); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/AttributesInCountryResponse.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/AttributesInCountryResponse.cs new file mode 100644 index 0000000000..cfea68f989 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/AttributesInCountryResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCountryResponse : global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// The population property + public long? Population + { + get { return BackingStore?.Get("population"); } + set { BackingStore?.Set("population", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInCountryResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInCountryResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "name", n => { Name = n.GetStringValue(); } }, + { "population", n => { Population = n.GetLongValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("name", Name); + writer.WriteLongValue("population", Population); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/AttributesInCreateCountryRequest.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/AttributesInCreateCountryRequest.cs new file mode 100644 index 0000000000..6b7377a82c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/AttributesInCreateCountryRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateCountryRequest : global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// The population property + public long? Population + { + get { return BackingStore?.Get("population"); } + set { BackingStore?.Set("population", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInCreateCountryRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInCreateCountryRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "name", n => { Name = n.GetStringValue(); } }, + { "population", n => { Population = n.GetLongValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("name", Name); + writer.WriteLongValue("population", Population); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/AttributesInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/AttributesInCreateRequest.cs new file mode 100644 index 0000000000..14dbfd1efb --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/AttributesInCreateRequest.cs @@ -0,0 +1,75 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "countries" => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInCreateCountryRequest(), + _ => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/AttributesInLanguageResponse.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/AttributesInLanguageResponse.cs new file mode 100644 index 0000000000..32d71abd9e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/AttributesInLanguageResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInLanguageResponse : global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The code property + public string? Code + { + get { return BackingStore?.Get("code"); } + set { BackingStore?.Set("code", value); } + } + + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInLanguageResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInLanguageResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "code", n => { Code = n.GetStringValue(); } }, + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("code", Code); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/AttributesInResponse.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/AttributesInResponse.cs new file mode 100644 index 0000000000..496a044efd --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/AttributesInResponse.cs @@ -0,0 +1,76 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "countries" => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInCountryResponse(), + "languages" => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInLanguageResponse(), + _ => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/AttributesInUpdateCountryRequest.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/AttributesInUpdateCountryRequest.cs new file mode 100644 index 0000000000..9b2f761daf --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/AttributesInUpdateCountryRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateCountryRequest : global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// The population property + public long? Population + { + get { return BackingStore?.Get("population"); } + set { BackingStore?.Set("population", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInUpdateCountryRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInUpdateCountryRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "name", n => { Name = n.GetStringValue(); } }, + { "population", n => { Population = n.GetLongValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("name", Name); + writer.WriteLongValue("population", Population); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/AttributesInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/AttributesInUpdateRequest.cs new file mode 100644 index 0000000000..6fd015c7a0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/AttributesInUpdateRequest.cs @@ -0,0 +1,75 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "countries" => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInUpdateCountryRequest(), + _ => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/CountryCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/CountryCollectionResponseDocument.cs new file mode 100644 index 0000000000..af711e741b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/CountryCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CountryCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CountryCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.CountryCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.CountryCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.DataInCountryResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/CreateCountryRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/CreateCountryRequestDocument.cs new file mode 100644 index 0000000000..0526ef9d9c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/CreateCountryRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateCountryRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.DataInCreateCountryRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateCountryRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.CreateCountryRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.CreateCountryRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.DataInCreateCountryRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/DataInCountryResponse.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/DataInCountryResponse.cs new file mode 100644 index 0000000000..2712a0367a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/DataInCountryResponse.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCountryResponse : global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInCountryResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInCountryResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.DataInCountryResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.DataInCountryResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInCountryResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetGuidValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInCountryResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteGuidValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/DataInCreateCountryRequest.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/DataInCreateCountryRequest.cs new file mode 100644 index 0000000000..7ce74c8b3d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/DataInCreateCountryRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateCountryRequest : global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInCreateCountryRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInCreateCountryRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.DataInCreateCountryRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.DataInCreateCountryRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInCreateCountryRequest.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInCreateCountryRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/DataInLanguageResponse.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/DataInLanguageResponse.cs new file mode 100644 index 0000000000..fb9e4a1a67 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/DataInLanguageResponse.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInLanguageResponse : global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInLanguageResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.DataInLanguageResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.DataInLanguageResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInLanguageResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetGuidValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteGuidValue("id", Id); + writer.WriteObjectValue("links", Links); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/DataInUpdateCountryRequest.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/DataInUpdateCountryRequest.cs new file mode 100644 index 0000000000..38bcdbfc4e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/DataInUpdateCountryRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateCountryRequest : global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInUpdateCountryRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInUpdateCountryRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.DataInUpdateCountryRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.DataInUpdateCountryRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.AttributesInUpdateCountryRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetGuidValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInUpdateCountryRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteGuidValue("id", Id); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ErrorLinks.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ErrorLinks.cs new file mode 100644 index 0000000000..4a2fe613b1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ErrorLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// The about property + public string? About + { + get { return BackingStore?.Get("about"); } + set { BackingStore?.Set("about", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The type property + public string? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "about", n => { About = n.GetStringValue(); } }, + { "type", n => { Type = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("about", About); + writer.WriteStringValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ErrorObject.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ErrorObject.cs new file mode 100644 index 0000000000..3badeb7798 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ErrorObject.cs @@ -0,0 +1,133 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorObject : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The code property + public string? Code + { + get { return BackingStore?.Get("code"); } + set { BackingStore?.Set("code", value); } + } + + /// The detail property + public string? Detail + { + get { return BackingStore?.Get("detail"); } + set { BackingStore?.Set("detail", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The source property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorSource? Source + { + get { return BackingStore?.Get("source"); } + set { BackingStore?.Set("source", value); } + } + + /// The status property + public string? Status + { + get { return BackingStore?.Get("status"); } + set { BackingStore?.Set("status", value); } + } + + /// The title property + public string? Title + { + get { return BackingStore?.Get("title"); } + set { BackingStore?.Set("title", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorObject() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorObject CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorObject(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "code", n => { Code = n.GetStringValue(); } }, + { "detail", n => { Detail = n.GetStringValue(); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "source", n => { Source = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorSource.CreateFromDiscriminatorValue); } }, + { "status", n => { Status = n.GetStringValue(); } }, + { "title", n => { Title = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("code", Code); + writer.WriteStringValue("detail", Detail); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + writer.WriteObjectValue("source", Source); + writer.WriteStringValue("status", Status); + writer.WriteStringValue("title", Title); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ErrorResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ErrorResponseDocument.cs new file mode 100644 index 0000000000..005c07a0a8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ErrorResponseDocument.cs @@ -0,0 +1,92 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorResponseDocument : ApiException, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The errors property + public List? Errors + { + get { return BackingStore?.Get?>("errors"); } + set { BackingStore?.Set("errors", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The primary error message. + public override string Message { get => base.Message; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "errors", n => { Errors = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorObject.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("errors", Errors); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ErrorSource.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ErrorSource.cs new file mode 100644 index 0000000000..0fae23f5a6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ErrorSource.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorSource : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The header property + public string? Header + { + get { return BackingStore?.Get("header"); } + set { BackingStore?.Set("header", value); } + } + + /// The parameter property + public string? Parameter + { + get { return BackingStore?.Get("parameter"); } + set { BackingStore?.Set("parameter", value); } + } + + /// The pointer property + public string? Pointer + { + get { return BackingStore?.Get("pointer"); } + set { BackingStore?.Set("pointer", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorSource() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorSource CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorSource(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "header", n => { Header = n.GetStringValue(); } }, + { "parameter", n => { Parameter = n.GetStringValue(); } }, + { "pointer", n => { Pointer = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("header", Header); + writer.WriteStringValue("parameter", Parameter); + writer.WriteStringValue("pointer", Pointer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ErrorTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ErrorTopLevelLinks.cs new file mode 100644 index 0000000000..d8154a4f2c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ErrorTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ErrorTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/IdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/IdentifierInRequest.cs new file mode 100644 index 0000000000..e84a79dd0b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/IdentifierInRequest.cs @@ -0,0 +1,84 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class IdentifierInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public IdentifierInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.IdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "languages" => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.LanguageIdentifierInRequest(), + _ => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.IdentifierInRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/LanguageCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/LanguageCollectionResponseDocument.cs new file mode 100644 index 0000000000..96fda5b57a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/LanguageCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class LanguageCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public LanguageCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.LanguageCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.LanguageCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.DataInLanguageResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/LanguageIdentifierCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/LanguageIdentifierCollectionResponseDocument.cs new file mode 100644 index 0000000000..e549d2c4d3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/LanguageIdentifierCollectionResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class LanguageIdentifierCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public LanguageIdentifierCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.LanguageIdentifierCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.LanguageIdentifierCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.LanguageIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/LanguageIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/LanguageIdentifierInRequest.cs new file mode 100644 index 0000000000..c1fbd8c800 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/LanguageIdentifierInRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class LanguageIdentifierInRequest : global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.LanguageIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.LanguageIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetGuidValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteGuidValue("id", Id); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/LanguageIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/LanguageIdentifierInResponse.cs new file mode 100644 index 0000000000..3c22a07b8e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/LanguageIdentifierInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class LanguageIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.LanguageResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public LanguageIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.LanguageIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.LanguageIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetGuidValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteGuidValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/LanguageResourceType.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/LanguageResourceType.cs new file mode 100644 index 0000000000..136ee3f03a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/LanguageResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum LanguageResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "languages")] + #pragma warning disable CS1591 + Languages, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/Meta.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/Meta.cs new file mode 100644 index 0000000000..52be8b831f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/Meta.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class Meta : IAdditionalDataHolder, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + public IDictionary AdditionalData + { + get { return BackingStore.Get>("AdditionalData") ?? new Dictionary(); } + set { BackingStore.Set("AdditionalData", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// + /// Instantiates a new and sets the default values. + /// + public Meta() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + AdditionalData = new Dictionary(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteAdditionalData(AdditionalData); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/PrimaryCountryResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/PrimaryCountryResponseDocument.cs new file mode 100644 index 0000000000..0f01d96dc2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/PrimaryCountryResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryCountryResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.DataInCountryResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryCountryResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.PrimaryCountryResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.PrimaryCountryResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.DataInCountryResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/RelationshipLinks.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/RelationshipLinks.cs new file mode 100644 index 0000000000..d2e8736256 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/RelationshipLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/RelationshipsInCountryResponse.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/RelationshipsInCountryResponse.cs new file mode 100644 index 0000000000..ad553a7e9b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/RelationshipsInCountryResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCountryResponse : global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// The languages property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ToManyLanguageInResponse? Languages + { + get { return BackingStore?.Get("languages"); } + set { BackingStore?.Set("languages", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInCountryResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInCountryResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "languages", n => { Languages = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ToManyLanguageInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("languages", Languages); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/RelationshipsInCreateCountryRequest.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/RelationshipsInCreateCountryRequest.cs new file mode 100644 index 0000000000..420df477b8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/RelationshipsInCreateCountryRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateCountryRequest : global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The languages property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ToManyLanguageInRequest? Languages + { + get { return BackingStore?.Get("languages"); } + set { BackingStore?.Set("languages", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInCreateCountryRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInCreateCountryRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "languages", n => { Languages = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ToManyLanguageInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("languages", Languages); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/RelationshipsInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/RelationshipsInCreateRequest.cs new file mode 100644 index 0000000000..2bc115a97e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/RelationshipsInCreateRequest.cs @@ -0,0 +1,75 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "countries" => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInCreateCountryRequest(), + _ => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/RelationshipsInResponse.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/RelationshipsInResponse.cs new file mode 100644 index 0000000000..79baa9aa61 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/RelationshipsInResponse.cs @@ -0,0 +1,75 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "countries" => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInCountryResponse(), + _ => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/RelationshipsInUpdateCountryRequest.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/RelationshipsInUpdateCountryRequest.cs new file mode 100644 index 0000000000..534b24bdf8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/RelationshipsInUpdateCountryRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateCountryRequest : global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The languages property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ToManyLanguageInRequest? Languages + { + get { return BackingStore?.Get("languages"); } + set { BackingStore?.Set("languages", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInUpdateCountryRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInUpdateCountryRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "languages", n => { Languages = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ToManyLanguageInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("languages", Languages); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/RelationshipsInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/RelationshipsInUpdateRequest.cs new file mode 100644 index 0000000000..eac5fe2ed1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/RelationshipsInUpdateRequest.cs @@ -0,0 +1,75 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "countries" => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInUpdateCountryRequest(), + _ => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipsInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceCollectionTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceCollectionTopLevelLinks.cs new file mode 100644 index 0000000000..3e601e6251 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceCollectionTopLevelLinks.cs @@ -0,0 +1,115 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceCollectionTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The first property + public string? First + { + get { return BackingStore?.Get("first"); } + set { BackingStore?.Set("first", value); } + } + + /// The last property + public string? Last + { + get { return BackingStore?.Get("last"); } + set { BackingStore?.Set("last", value); } + } + + /// The next property + public string? Next + { + get { return BackingStore?.Get("next"); } + set { BackingStore?.Set("next", value); } + } + + /// The prev property + public string? Prev + { + get { return BackingStore?.Get("prev"); } + set { BackingStore?.Set("prev", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceCollectionTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceCollectionTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceCollectionTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "first", n => { First = n.GetStringValue(); } }, + { "last", n => { Last = n.GetStringValue(); } }, + { "next", n => { Next = n.GetStringValue(); } }, + { "prev", n => { Prev = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("first", First); + writer.WriteStringValue("last", Last); + writer.WriteStringValue("next", Next); + writer.WriteStringValue("prev", Prev); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs new file mode 100644 index 0000000000..fcbe538659 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs @@ -0,0 +1,124 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceIdentifierCollectionTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The first property + public string? First + { + get { return BackingStore?.Get("first"); } + set { BackingStore?.Set("first", value); } + } + + /// The last property + public string? Last + { + get { return BackingStore?.Get("last"); } + set { BackingStore?.Set("last", value); } + } + + /// The next property + public string? Next + { + get { return BackingStore?.Get("next"); } + set { BackingStore?.Set("next", value); } + } + + /// The prev property + public string? Prev + { + get { return BackingStore?.Get("prev"); } + set { BackingStore?.Set("prev", value); } + } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceIdentifierCollectionTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "first", n => { First = n.GetStringValue(); } }, + { "last", n => { Last = n.GetStringValue(); } }, + { "next", n => { Next = n.GetStringValue(); } }, + { "prev", n => { Prev = n.GetStringValue(); } }, + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("first", First); + writer.WriteStringValue("last", Last); + writer.WriteStringValue("next", Next); + writer.WriteStringValue("prev", Prev); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceInCreateRequest.cs new file mode 100644 index 0000000000..b5cf81cd00 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceInCreateRequest.cs @@ -0,0 +1,84 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "countries" => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.DataInCreateCountryRequest(), + _ => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceInResponse.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceInResponse.cs new file mode 100644 index 0000000000..8cbdaf46ed --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceInResponse.cs @@ -0,0 +1,85 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "countries" => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.DataInCountryResponse(), + "languages" => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.DataInLanguageResponse(), + _ => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceInUpdateRequest.cs new file mode 100644 index 0000000000..09f5c48d1a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceInUpdateRequest.cs @@ -0,0 +1,84 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "countries" => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.DataInUpdateCountryRequest(), + _ => new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceLinks.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceLinks.cs new file mode 100644 index 0000000000..42f9aaa346 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceLinks.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceTopLevelLinks.cs new file mode 100644 index 0000000000..177c956af0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ResourceTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceType.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceType.cs new file mode 100644 index 0000000000..b43e2a7d26 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ResourceType.cs @@ -0,0 +1,22 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum ResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "countries")] + #pragma warning disable CS1591 + Countries, + #pragma warning restore CS1591 + [EnumMember(Value = "languages")] + #pragma warning disable CS1591 + Languages, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ToManyLanguageInRequest.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ToManyLanguageInRequest.cs new file mode 100644 index 0000000000..21a29da60b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ToManyLanguageInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyLanguageInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyLanguageInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ToManyLanguageInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ToManyLanguageInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.LanguageIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ToManyLanguageInResponse.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ToManyLanguageInResponse.cs new file mode 100644 index 0000000000..13fb140c45 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/ToManyLanguageInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyLanguageInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyLanguageInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ToManyLanguageInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.ToManyLanguageInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.LanguageIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/UpdateCountryRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/UpdateCountryRequestDocument.cs new file mode 100644 index 0000000000..468b58fdc7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/Models/UpdateCountryRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateCountryRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.DataInUpdateCountryRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateCountryRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.UpdateCountryRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.UpdateCountryRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.DataInUpdateCountryRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Headers/HeaderTests.cs b/test/OpenApiKiotaEndToEndTests/Headers/HeaderTests.cs new file mode 100644 index 0000000000..b42071a6af --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/HeaderTests.cs @@ -0,0 +1,192 @@ +using FluentAssertions; +using Microsoft.Kiota.Http.HttpClientLibrary; +using Microsoft.Kiota.Http.HttpClientLibrary.Middleware.Options; +using Microsoft.Net.Http.Headers; +using OpenApiKiotaEndToEndTests.Headers.GeneratedCode; +using OpenApiKiotaEndToEndTests.Headers.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.Headers; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.Headers; + +public sealed class HeaderTests : IClassFixture, HeaderDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, HeaderDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly HeaderFakers _fakers = new(); + + public HeaderTests(IntegrationTestContext, HeaderDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseController(); + } + + [Fact] + public async Task Returns_Location_for_post_resource_request() + { + // Arrange + Country newCountry = _fakers.Country.GenerateOne(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new HeadersClient(requestAdapter); + + var headerInspector = new HeadersInspectionHandlerOption + { + InspectResponseHeaders = true + }; + + var requestBody = new CreateCountryRequestDocument + { + Data = new DataInCreateCountryRequest + { + Type = ResourceType.Countries, + Attributes = new AttributesInCreateCountryRequest + { + Name = newCountry.Name, + Population = newCountry.Population + } + } + }; + + // Act + PrimaryCountryResponseDocument? response = + await apiClient.Countries.PostAsync(requestBody, configuration => configuration.Options.Add(headerInspector)); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().NotBeNull(); + + string[] locationHeaderValues = headerInspector.ResponseHeaders.Should().ContainKey(HeaderNames.Location).WhoseValue.ToArray(); + locationHeaderValues.Should().HaveCount(1); + locationHeaderValues[0].Should().Be($"/countries/{response.Data.Id}"); + } + + [Fact] + public async Task Returns_ContentLength_for_head_primary_resources_request() + { + // Arrange + Country existingCountry = _fakers.Country.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Countries.Add(existingCountry); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new HeadersClient(requestAdapter); + + var headerInspector = new HeadersInspectionHandlerOption + { + InspectResponseHeaders = true + }; + + // Act + await apiClient.Countries.HeadAsync(configuration => configuration.Options.Add(headerInspector)); + + // Assert + string[] contentLengthHeaderValues = headerInspector.ResponseHeaders.Should().ContainKey(HeaderNames.ContentLength).WhoseValue.ToArray(); + contentLengthHeaderValues.Should().HaveCount(1); + long.Parse(contentLengthHeaderValues[0]).Should().BeGreaterThan(0); + } + + [Fact] + public async Task Returns_ContentLength_for_head_primary_resource_request() + { + // Arrange + Country existingCountry = _fakers.Country.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Countries.Add(existingCountry); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new HeadersClient(requestAdapter); + + var headerInspector = new HeadersInspectionHandlerOption + { + InspectResponseHeaders = true + }; + + // Act + await apiClient.Countries[existingCountry.Id].HeadAsync(configuration => configuration.Options.Add(headerInspector)); + + // Assert + string[] contentLengthHeaderValues = headerInspector.ResponseHeaders.Should().ContainKey(HeaderNames.ContentLength).WhoseValue.ToArray(); + contentLengthHeaderValues.Should().HaveCount(1); + long.Parse(contentLengthHeaderValues[0]).Should().BeGreaterThan(0); + } + + [Fact] + public async Task Returns_ContentLength_for_head_secondary_resource_request() + { + // Arrange + Country existingCountry = _fakers.Country.GenerateOne(); + existingCountry.Languages = _fakers.Language.GenerateSet(1); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Countries.Add(existingCountry); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new HeadersClient(requestAdapter); + + var headerInspector = new HeadersInspectionHandlerOption + { + InspectResponseHeaders = true + }; + + // Act + await apiClient.Countries[existingCountry.Id].Languages.HeadAsync(configuration => configuration.Options.Add(headerInspector)); + + // Assert + string[] contentLengthHeaderValues = headerInspector.ResponseHeaders.Should().ContainKey(HeaderNames.ContentLength).WhoseValue.ToArray(); + contentLengthHeaderValues.Should().HaveCount(1); + long.Parse(contentLengthHeaderValues[0]).Should().BeGreaterThan(0); + } + + [Fact] + public async Task Returns_ContentLength_for_head_relationship_request() + { + // Arrange + Country existingCountry = _fakers.Country.GenerateOne(); + existingCountry.Languages = _fakers.Language.GenerateSet(1); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Countries.Add(existingCountry); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new HeadersClient(requestAdapter); + + var headerInspector = new HeadersInspectionHandlerOption + { + InspectResponseHeaders = true + }; + + // Act + await apiClient.Countries[existingCountry.Id].Relationships.Languages.HeadAsync(configuration => configuration.Options.Add(headerInspector)); + + // Assert + string[] contentLengthHeaderValues = headerInspector.ResponseHeaders.Should().ContainKey(HeaderNames.ContentLength).WhoseValue.ToArray(); + contentLengthHeaderValues.Should().HaveCount(1); + long.Parse(contentLengthHeaderValues[0]).Should().BeGreaterThan(0); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/Links/AlternateOpenApiRouteTests.cs b/test/OpenApiKiotaEndToEndTests/Links/AlternateOpenApiRouteTests.cs new file mode 100644 index 0000000000..b27fbf28fe --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/AlternateOpenApiRouteTests.cs @@ -0,0 +1,60 @@ +using FluentAssertions; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.Links; +using Swashbuckle.AspNetCore.Swagger; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.Links; + +public sealed class AlternateOpenApiRouteTests : IClassFixture, LinkDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, LinkDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly LinkFakers _fakers = new(); + + public AlternateOpenApiRouteTests(IntegrationTestContext, LinkDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.ConfigureServices(services => + services.Configure(options => options.RouteTemplate = "/api-docs/{documentName}/swagger.yaml")); + + testContext.UseController(); + } + + [Fact] + public async Task DescribedBy_link_matches_alternate_OpenAPI_route() + { + // Arrange + Excursion excursion = _fakers.Excursion.GenerateOne(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new LinksClient(requestAdapter); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Excursions.Add(excursion); + await dbContext.SaveChangesAsync(); + }); + + // Act + PrimaryExcursionResponseDocument? response = await apiClient.Excursions[excursion.StringId!].GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Links.Should().NotBeNull(); + response.Links.Describedby.Should().Be("/api-docs/v1/swagger.yaml"); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Accommodations/AccommodationsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Accommodations/AccommodationsRequestBuilder.cs new file mode 100644 index 0000000000..0e9bc39d41 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Accommodations/AccommodationsRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Accommodations.Item; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Accommodations +{ + /// + /// Builds and executes requests for operations under \accommodations + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AccommodationsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.Links.GeneratedCode.accommodations.item collection + /// The identifier of the accommodation to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Accommodations.Item.AccommodationsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Accommodations.Item.AccommodationsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public AccommodationsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/accommodations{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public AccommodationsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/accommodations{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of accommodations. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AccommodationCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new accommodation. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.CreateAccommodationRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.PrimaryAccommodationResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of accommodations. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new accommodation. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.CreateAccommodationRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Accommodations.AccommodationsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Accommodations.AccommodationsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of accommodations. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AccommodationsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AccommodationsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new accommodation. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AccommodationsRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Accommodations/Item/AccommodationsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Accommodations/Item/AccommodationsItemRequestBuilder.cs new file mode 100644 index 0000000000..145408614f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Accommodations/Item/AccommodationsItemRequestBuilder.cs @@ -0,0 +1,209 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Accommodations.Item +{ + /// + /// Builds and executes requests for operations under \accommodations\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AccommodationsItemRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public AccommodationsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/accommodations/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public AccommodationsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/accommodations/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing accommodation by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual accommodation by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.PrimaryAccommodationResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing accommodation. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.UpdateAccommodationRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.PrimaryAccommodationResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing accommodation by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual accommodation by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing accommodation. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.UpdateAccommodationRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Accommodations.Item.AccommodationsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Accommodations.Item.AccommodationsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual accommodation by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AccommodationsItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AccommodationsItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing accommodation. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AccommodationsItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Excursions/ExcursionsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Excursions/ExcursionsRequestBuilder.cs new file mode 100644 index 0000000000..c522dd0299 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Excursions/ExcursionsRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Excursions.Item; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Excursions +{ + /// + /// Builds and executes requests for operations under \excursions + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ExcursionsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.Links.GeneratedCode.excursions.item collection + /// The identifier of the excursion to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Excursions.Item.ExcursionsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Excursions.Item.ExcursionsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ExcursionsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/excursions{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ExcursionsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/excursions{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of excursions. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ExcursionCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new excursion. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.CreateExcursionRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.PrimaryExcursionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of excursions. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new excursion. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.CreateExcursionRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Excursions.ExcursionsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Excursions.ExcursionsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of excursions. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ExcursionsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ExcursionsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new excursion. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ExcursionsRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Excursions/Item/ExcursionsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Excursions/Item/ExcursionsItemRequestBuilder.cs new file mode 100644 index 0000000000..97119404bd --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Excursions/Item/ExcursionsItemRequestBuilder.cs @@ -0,0 +1,209 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Excursions.Item +{ + /// + /// Builds and executes requests for operations under \excursions\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ExcursionsItemRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ExcursionsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/excursions/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ExcursionsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/excursions/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing excursion by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual excursion by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.PrimaryExcursionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing excursion. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.UpdateExcursionRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.PrimaryExcursionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing excursion by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual excursion by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing excursion. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.UpdateExcursionRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Excursions.Item.ExcursionsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Excursions.Item.ExcursionsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual excursion by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ExcursionsItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ExcursionsItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing excursion. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ExcursionsItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/LinksClient.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/LinksClient.cs new file mode 100644 index 0000000000..1131bc2a70 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/LinksClient.cs @@ -0,0 +1,75 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using Microsoft.Kiota.Serialization.Form; +using Microsoft.Kiota.Serialization.Json; +using Microsoft.Kiota.Serialization.Multipart; +using Microsoft.Kiota.Serialization.Text; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Accommodations; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Excursions; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Transports; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode +{ + /// + /// The main entry point of the SDK, exposes the configuration and the fluent API. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class LinksClient : BaseRequestBuilder + { + /// The accommodations property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Accommodations.AccommodationsRequestBuilder Accommodations + { + get => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Accommodations.AccommodationsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The excursions property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Excursions.ExcursionsRequestBuilder Excursions + { + get => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Excursions.ExcursionsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The transports property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Transports.TransportsRequestBuilder Transports + { + get => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Transports.TransportsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The vacations property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.VacationsRequestBuilder Vacations + { + get => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.VacationsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The backing store to use for the models. + /// The request adapter to use to execute the requests. + public LinksClient(IRequestAdapter requestAdapter, IBackingStoreFactory backingStore = default) : base(requestAdapter, "{+baseurl}", new Dictionary()) + { + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + if (string.IsNullOrEmpty(RequestAdapter.BaseUrl)) + { + RequestAdapter.BaseUrl = "http://localhost"; + } + PathParameters.TryAdd("baseurl", RequestAdapter.BaseUrl); + RequestAdapter.EnableBackingStore(backingStore); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AccommodationCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AccommodationCollectionResponseDocument.cs new file mode 100644 index 0000000000..fb7558f277 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AccommodationCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AccommodationCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AccommodationCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AccommodationCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AccommodationCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInAccommodationResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AccommodationIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AccommodationIdentifierInRequest.cs new file mode 100644 index 0000000000..aae4d490d4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AccommodationIdentifierInRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AccommodationIdentifierInRequest : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AccommodationIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AccommodationIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AccommodationIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AccommodationIdentifierInResponse.cs new file mode 100644 index 0000000000..991f213ec9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AccommodationIdentifierInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AccommodationIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AccommodationResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AccommodationIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AccommodationIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AccommodationIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AccommodationIdentifierResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AccommodationIdentifierResponseDocument.cs new file mode 100644 index 0000000000..8ae07dbd2b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AccommodationIdentifierResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AccommodationIdentifierResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AccommodationIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceIdentifierTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AccommodationIdentifierResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AccommodationIdentifierResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AccommodationIdentifierResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AccommodationIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceIdentifierTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AccommodationResourceType.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AccommodationResourceType.cs new file mode 100644 index 0000000000..69079e56b2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AccommodationResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum AccommodationResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "accommodations")] + #pragma warning disable CS1591 + Accommodations, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInAccommodationResponse.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInAccommodationResponse.cs new file mode 100644 index 0000000000..08015788a2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInAccommodationResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInAccommodationResponse : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The address property + public string? Address + { + get { return BackingStore?.Get("address"); } + set { BackingStore?.Set("address", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInAccommodationResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInAccommodationResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "address", n => { Address = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("address", Address); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInCreateAccommodationRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInCreateAccommodationRequest.cs new file mode 100644 index 0000000000..99ccaec809 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInCreateAccommodationRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateAccommodationRequest : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The address property + public string? Address + { + get { return BackingStore?.Get("address"); } + set { BackingStore?.Set("address", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateAccommodationRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateAccommodationRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "address", n => { Address = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("address", Address); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInCreateExcursionRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInCreateExcursionRequest.cs new file mode 100644 index 0000000000..2479302ede --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInCreateExcursionRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateExcursionRequest : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The description property + public string? Description + { + get { return BackingStore?.Get("description"); } + set { BackingStore?.Set("description", value); } + } + + /// The occursAt property + public DateTimeOffset? OccursAt + { + get { return BackingStore?.Get("occursAt"); } + set { BackingStore?.Set("occursAt", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateExcursionRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateExcursionRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "description", n => { Description = n.GetStringValue(); } }, + { "occursAt", n => { OccursAt = n.GetDateTimeOffsetValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("description", Description); + writer.WriteDateTimeOffsetValue("occursAt", OccursAt); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInCreateRequest.cs new file mode 100644 index 0000000000..bcca0e9803 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInCreateRequest.cs @@ -0,0 +1,78 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "accommodations" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateAccommodationRequest(), + "excursions" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateExcursionRequest(), + "transports" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateTransportRequest(), + "vacations" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateVacationRequest(), + _ => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInCreateTransportRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInCreateTransportRequest.cs new file mode 100644 index 0000000000..06f4cf39e3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInCreateTransportRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateTransportRequest : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The durationInMinutes property + public int? DurationInMinutes + { + get { return BackingStore?.Get("durationInMinutes"); } + set { BackingStore?.Set("durationInMinutes", value); } + } + + /// The type property + public int? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateTransportRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateTransportRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "durationInMinutes", n => { DurationInMinutes = n.GetIntValue(); } }, + { "type", n => { Type = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("durationInMinutes", DurationInMinutes); + writer.WriteIntValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInCreateVacationRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInCreateVacationRequest.cs new file mode 100644 index 0000000000..811ad4e362 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInCreateVacationRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateVacationRequest : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The endsAt property + public DateTimeOffset? EndsAt + { + get { return BackingStore?.Get("endsAt"); } + set { BackingStore?.Set("endsAt", value); } + } + + /// The startsAt property + public DateTimeOffset? StartsAt + { + get { return BackingStore?.Get("startsAt"); } + set { BackingStore?.Set("startsAt", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateVacationRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateVacationRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "endsAt", n => { EndsAt = n.GetDateTimeOffsetValue(); } }, + { "startsAt", n => { StartsAt = n.GetDateTimeOffsetValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteDateTimeOffsetValue("endsAt", EndsAt); + writer.WriteDateTimeOffsetValue("startsAt", StartsAt); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInExcursionResponse.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInExcursionResponse.cs new file mode 100644 index 0000000000..7c831ef525 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInExcursionResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInExcursionResponse : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The description property + public string? Description + { + get { return BackingStore?.Get("description"); } + set { BackingStore?.Set("description", value); } + } + + /// The occursAt property + public DateTimeOffset? OccursAt + { + get { return BackingStore?.Get("occursAt"); } + set { BackingStore?.Set("occursAt", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInExcursionResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInExcursionResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "description", n => { Description = n.GetStringValue(); } }, + { "occursAt", n => { OccursAt = n.GetDateTimeOffsetValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("description", Description); + writer.WriteDateTimeOffsetValue("occursAt", OccursAt); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInResponse.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInResponse.cs new file mode 100644 index 0000000000..cb3437aec3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInResponse.cs @@ -0,0 +1,78 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "accommodations" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInAccommodationResponse(), + "excursions" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInExcursionResponse(), + "transports" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInTransportResponse(), + "vacations" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInVacationResponse(), + _ => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInTransportResponse.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInTransportResponse.cs new file mode 100644 index 0000000000..ae69b72286 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInTransportResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInTransportResponse : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The durationInMinutes property + public int? DurationInMinutes + { + get { return BackingStore?.Get("durationInMinutes"); } + set { BackingStore?.Set("durationInMinutes", value); } + } + + /// The type property + public int? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInTransportResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInTransportResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "durationInMinutes", n => { DurationInMinutes = n.GetIntValue(); } }, + { "type", n => { Type = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("durationInMinutes", DurationInMinutes); + writer.WriteIntValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInUpdateAccommodationRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInUpdateAccommodationRequest.cs new file mode 100644 index 0000000000..a407e9978b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInUpdateAccommodationRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateAccommodationRequest : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The address property + public string? Address + { + get { return BackingStore?.Get("address"); } + set { BackingStore?.Set("address", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateAccommodationRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateAccommodationRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "address", n => { Address = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("address", Address); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInUpdateExcursionRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInUpdateExcursionRequest.cs new file mode 100644 index 0000000000..f69cac01a9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInUpdateExcursionRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateExcursionRequest : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The description property + public string? Description + { + get { return BackingStore?.Get("description"); } + set { BackingStore?.Set("description", value); } + } + + /// The occursAt property + public DateTimeOffset? OccursAt + { + get { return BackingStore?.Get("occursAt"); } + set { BackingStore?.Set("occursAt", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateExcursionRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateExcursionRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "description", n => { Description = n.GetStringValue(); } }, + { "occursAt", n => { OccursAt = n.GetDateTimeOffsetValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("description", Description); + writer.WriteDateTimeOffsetValue("occursAt", OccursAt); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInUpdateRequest.cs new file mode 100644 index 0000000000..5deb0f1a93 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInUpdateRequest.cs @@ -0,0 +1,78 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "accommodations" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateAccommodationRequest(), + "excursions" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateExcursionRequest(), + "transports" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateTransportRequest(), + "vacations" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateVacationRequest(), + _ => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInUpdateTransportRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInUpdateTransportRequest.cs new file mode 100644 index 0000000000..3450183500 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInUpdateTransportRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateTransportRequest : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The durationInMinutes property + public int? DurationInMinutes + { + get { return BackingStore?.Get("durationInMinutes"); } + set { BackingStore?.Set("durationInMinutes", value); } + } + + /// The type property + public int? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateTransportRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateTransportRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "durationInMinutes", n => { DurationInMinutes = n.GetIntValue(); } }, + { "type", n => { Type = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("durationInMinutes", DurationInMinutes); + writer.WriteIntValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInUpdateVacationRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInUpdateVacationRequest.cs new file mode 100644 index 0000000000..4826779630 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInUpdateVacationRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateVacationRequest : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The endsAt property + public DateTimeOffset? EndsAt + { + get { return BackingStore?.Get("endsAt"); } + set { BackingStore?.Set("endsAt", value); } + } + + /// The startsAt property + public DateTimeOffset? StartsAt + { + get { return BackingStore?.Get("startsAt"); } + set { BackingStore?.Set("startsAt", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateVacationRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateVacationRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "endsAt", n => { EndsAt = n.GetDateTimeOffsetValue(); } }, + { "startsAt", n => { StartsAt = n.GetDateTimeOffsetValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteDateTimeOffsetValue("endsAt", EndsAt); + writer.WriteDateTimeOffsetValue("startsAt", StartsAt); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInVacationResponse.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInVacationResponse.cs new file mode 100644 index 0000000000..2f19135f5b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/AttributesInVacationResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInVacationResponse : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The endsAt property + public DateTimeOffset? EndsAt + { + get { return BackingStore?.Get("endsAt"); } + set { BackingStore?.Set("endsAt", value); } + } + + /// The startsAt property + public DateTimeOffset? StartsAt + { + get { return BackingStore?.Get("startsAt"); } + set { BackingStore?.Set("startsAt", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInVacationResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInVacationResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "endsAt", n => { EndsAt = n.GetDateTimeOffsetValue(); } }, + { "startsAt", n => { StartsAt = n.GetDateTimeOffsetValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteDateTimeOffsetValue("endsAt", EndsAt); + writer.WriteDateTimeOffsetValue("startsAt", StartsAt); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/CreateAccommodationRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/CreateAccommodationRequestDocument.cs new file mode 100644 index 0000000000..88fb66d856 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/CreateAccommodationRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateAccommodationRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInCreateAccommodationRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateAccommodationRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.CreateAccommodationRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.CreateAccommodationRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInCreateAccommodationRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/CreateExcursionRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/CreateExcursionRequestDocument.cs new file mode 100644 index 0000000000..9a9ec39d7c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/CreateExcursionRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateExcursionRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInCreateExcursionRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateExcursionRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.CreateExcursionRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.CreateExcursionRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInCreateExcursionRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/CreateTransportRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/CreateTransportRequestDocument.cs new file mode 100644 index 0000000000..3eb47dd37a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/CreateTransportRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateTransportRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInCreateTransportRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateTransportRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.CreateTransportRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.CreateTransportRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInCreateTransportRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/CreateVacationRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/CreateVacationRequestDocument.cs new file mode 100644 index 0000000000..58660a4c20 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/CreateVacationRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateVacationRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInCreateVacationRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateVacationRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.CreateVacationRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.CreateVacationRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInCreateVacationRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInAccommodationResponse.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInAccommodationResponse.cs new file mode 100644 index 0000000000..0897645649 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInAccommodationResponse.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInAccommodationResponse : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInAccommodationResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInAccommodationResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInAccommodationResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInAccommodationResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInCreateAccommodationRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInCreateAccommodationRequest.cs new file mode 100644 index 0000000000..c15b5b21e8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInCreateAccommodationRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateAccommodationRequest : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateAccommodationRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInCreateAccommodationRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInCreateAccommodationRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateAccommodationRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInCreateExcursionRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInCreateExcursionRequest.cs new file mode 100644 index 0000000000..e0601a86b7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInCreateExcursionRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateExcursionRequest : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateExcursionRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInCreateExcursionRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInCreateExcursionRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateExcursionRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInCreateTransportRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInCreateTransportRequest.cs new file mode 100644 index 0000000000..7fe0892ac9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInCreateTransportRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateTransportRequest : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateTransportRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInCreateTransportRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInCreateTransportRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateTransportRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInCreateVacationRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInCreateVacationRequest.cs new file mode 100644 index 0000000000..c17c50264f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInCreateVacationRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateVacationRequest : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateVacationRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInCreateVacationRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInCreateVacationRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInCreateVacationRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInCreateVacationRequest.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInCreateVacationRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInExcursionResponse.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInExcursionResponse.cs new file mode 100644 index 0000000000..c18d507d5c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInExcursionResponse.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInExcursionResponse : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInExcursionResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInExcursionResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInExcursionResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInExcursionResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInTransportResponse.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInTransportResponse.cs new file mode 100644 index 0000000000..4c0d872b89 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInTransportResponse.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInTransportResponse : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInTransportResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInTransportResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInTransportResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInTransportResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInUpdateAccommodationRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInUpdateAccommodationRequest.cs new file mode 100644 index 0000000000..16d4fd8a2c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInUpdateAccommodationRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateAccommodationRequest : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateAccommodationRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInUpdateAccommodationRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInUpdateAccommodationRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateAccommodationRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInUpdateExcursionRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInUpdateExcursionRequest.cs new file mode 100644 index 0000000000..e25c8fbfab --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInUpdateExcursionRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateExcursionRequest : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateExcursionRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInUpdateExcursionRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInUpdateExcursionRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateExcursionRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInUpdateTransportRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInUpdateTransportRequest.cs new file mode 100644 index 0000000000..797d61a73d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInUpdateTransportRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateTransportRequest : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateTransportRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInUpdateTransportRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInUpdateTransportRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateTransportRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInUpdateVacationRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInUpdateVacationRequest.cs new file mode 100644 index 0000000000..a53cee4371 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInUpdateVacationRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateVacationRequest : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateVacationRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInUpdateVacationRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInUpdateVacationRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInUpdateVacationRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInUpdateVacationRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInUpdateVacationRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInVacationResponse.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInVacationResponse.cs new file mode 100644 index 0000000000..1cad15d111 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/DataInVacationResponse.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInVacationResponse : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInVacationResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInVacationResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInVacationResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInVacationResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AttributesInVacationResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInVacationResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ErrorLinks.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ErrorLinks.cs new file mode 100644 index 0000000000..bdba746cc4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ErrorLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// The about property + public string? About + { + get { return BackingStore?.Get("about"); } + set { BackingStore?.Set("about", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The type property + public string? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "about", n => { About = n.GetStringValue(); } }, + { "type", n => { Type = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("about", About); + writer.WriteStringValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ErrorObject.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ErrorObject.cs new file mode 100644 index 0000000000..80d825c917 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ErrorObject.cs @@ -0,0 +1,133 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorObject : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The code property + public string? Code + { + get { return BackingStore?.Get("code"); } + set { BackingStore?.Set("code", value); } + } + + /// The detail property + public string? Detail + { + get { return BackingStore?.Get("detail"); } + set { BackingStore?.Set("detail", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The source property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorSource? Source + { + get { return BackingStore?.Get("source"); } + set { BackingStore?.Set("source", value); } + } + + /// The status property + public string? Status + { + get { return BackingStore?.Get("status"); } + set { BackingStore?.Set("status", value); } + } + + /// The title property + public string? Title + { + get { return BackingStore?.Get("title"); } + set { BackingStore?.Set("title", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorObject() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorObject CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorObject(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "code", n => { Code = n.GetStringValue(); } }, + { "detail", n => { Detail = n.GetStringValue(); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "source", n => { Source = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorSource.CreateFromDiscriminatorValue); } }, + { "status", n => { Status = n.GetStringValue(); } }, + { "title", n => { Title = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("code", Code); + writer.WriteStringValue("detail", Detail); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + writer.WriteObjectValue("source", Source); + writer.WriteStringValue("status", Status); + writer.WriteStringValue("title", Title); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ErrorResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ErrorResponseDocument.cs new file mode 100644 index 0000000000..c36db2256c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ErrorResponseDocument.cs @@ -0,0 +1,92 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorResponseDocument : ApiException, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The errors property + public List? Errors + { + get { return BackingStore?.Get?>("errors"); } + set { BackingStore?.Set("errors", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The primary error message. + public override string Message { get => base.Message; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "errors", n => { Errors = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorObject.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("errors", Errors); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ErrorSource.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ErrorSource.cs new file mode 100644 index 0000000000..3164110971 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ErrorSource.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorSource : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The header property + public string? Header + { + get { return BackingStore?.Get("header"); } + set { BackingStore?.Set("header", value); } + } + + /// The parameter property + public string? Parameter + { + get { return BackingStore?.Get("parameter"); } + set { BackingStore?.Set("parameter", value); } + } + + /// The pointer property + public string? Pointer + { + get { return BackingStore?.Get("pointer"); } + set { BackingStore?.Set("pointer", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorSource() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorSource CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorSource(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "header", n => { Header = n.GetStringValue(); } }, + { "parameter", n => { Parameter = n.GetStringValue(); } }, + { "pointer", n => { Pointer = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("header", Header); + writer.WriteStringValue("parameter", Parameter); + writer.WriteStringValue("pointer", Pointer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ErrorTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ErrorTopLevelLinks.cs new file mode 100644 index 0000000000..300ddff394 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ErrorTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ExcursionCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ExcursionCollectionResponseDocument.cs new file mode 100644 index 0000000000..bde5dd575c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ExcursionCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ExcursionCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ExcursionCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ExcursionCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ExcursionCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInExcursionResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ExcursionIdentifierCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ExcursionIdentifierCollectionResponseDocument.cs new file mode 100644 index 0000000000..1a51a7b660 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ExcursionIdentifierCollectionResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ExcursionIdentifierCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ExcursionIdentifierCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ExcursionIdentifierCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ExcursionIdentifierCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ExcursionIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ExcursionIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ExcursionIdentifierInRequest.cs new file mode 100644 index 0000000000..5ff36171cf --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ExcursionIdentifierInRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ExcursionIdentifierInRequest : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ExcursionIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ExcursionIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ExcursionIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ExcursionIdentifierInResponse.cs new file mode 100644 index 0000000000..9d2d3ffd44 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ExcursionIdentifierInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ExcursionIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ExcursionResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ExcursionIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ExcursionIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ExcursionIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ExcursionResourceType.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ExcursionResourceType.cs new file mode 100644 index 0000000000..36480b06b7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ExcursionResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum ExcursionResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "excursions")] + #pragma warning disable CS1591 + Excursions, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/IdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/IdentifierInRequest.cs new file mode 100644 index 0000000000..2909b955ac --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/IdentifierInRequest.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class IdentifierInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public IdentifierInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.IdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "accommodations" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AccommodationIdentifierInRequest(), + "excursions" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ExcursionIdentifierInRequest(), + "transports" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.TransportIdentifierInRequest(), + _ => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.IdentifierInRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/Meta.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/Meta.cs new file mode 100644 index 0000000000..c6718c7d6b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/Meta.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class Meta : IAdditionalDataHolder, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + public IDictionary AdditionalData + { + get { return BackingStore.Get>("AdditionalData") ?? new Dictionary(); } + set { BackingStore.Set("AdditionalData", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// + /// Instantiates a new and sets the default values. + /// + public Meta() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + AdditionalData = new Dictionary(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteAdditionalData(AdditionalData); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/NullableSecondaryTransportResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/NullableSecondaryTransportResponseDocument.cs new file mode 100644 index 0000000000..2956c71ea8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/NullableSecondaryTransportResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NullableSecondaryTransportResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInTransportResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NullableSecondaryTransportResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.NullableSecondaryTransportResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.NullableSecondaryTransportResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInTransportResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/NullableToOneTransportInRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/NullableToOneTransportInRequest.cs new file mode 100644 index 0000000000..84e33c6676 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/NullableToOneTransportInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NullableToOneTransportInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.TransportIdentifierInRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NullableToOneTransportInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.NullableToOneTransportInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.NullableToOneTransportInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.TransportIdentifierInRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/NullableToOneTransportInResponse.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/NullableToOneTransportInResponse.cs new file mode 100644 index 0000000000..9a0c40af4b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/NullableToOneTransportInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NullableToOneTransportInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.TransportIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NullableToOneTransportInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.NullableToOneTransportInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.NullableToOneTransportInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.TransportIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/NullableTransportIdentifierResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/NullableTransportIdentifierResponseDocument.cs new file mode 100644 index 0000000000..f98b944aa7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/NullableTransportIdentifierResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NullableTransportIdentifierResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.TransportIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceIdentifierTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NullableTransportIdentifierResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.NullableTransportIdentifierResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.NullableTransportIdentifierResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.TransportIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceIdentifierTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/PrimaryAccommodationResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/PrimaryAccommodationResponseDocument.cs new file mode 100644 index 0000000000..c06dd1abeb --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/PrimaryAccommodationResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryAccommodationResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInAccommodationResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryAccommodationResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.PrimaryAccommodationResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.PrimaryAccommodationResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInAccommodationResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/PrimaryExcursionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/PrimaryExcursionResponseDocument.cs new file mode 100644 index 0000000000..8b690688d4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/PrimaryExcursionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryExcursionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInExcursionResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryExcursionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.PrimaryExcursionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.PrimaryExcursionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInExcursionResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/PrimaryTransportResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/PrimaryTransportResponseDocument.cs new file mode 100644 index 0000000000..09bb6d5cb5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/PrimaryTransportResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryTransportResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInTransportResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryTransportResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.PrimaryTransportResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.PrimaryTransportResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInTransportResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/PrimaryVacationResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/PrimaryVacationResponseDocument.cs new file mode 100644 index 0000000000..aa4f702d38 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/PrimaryVacationResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryVacationResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInVacationResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryVacationResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.PrimaryVacationResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.PrimaryVacationResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInVacationResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/RelationshipLinks.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/RelationshipLinks.cs new file mode 100644 index 0000000000..cb51f647c7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/RelationshipLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/RelationshipsInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/RelationshipsInCreateRequest.cs new file mode 100644 index 0000000000..59563b8f0b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/RelationshipsInCreateRequest.cs @@ -0,0 +1,75 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "vacations" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInCreateVacationRequest(), + _ => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/RelationshipsInCreateVacationRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/RelationshipsInCreateVacationRequest.cs new file mode 100644 index 0000000000..c4e7a6032b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/RelationshipsInCreateVacationRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateVacationRequest : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The accommodation property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToOneAccommodationInRequest? Accommodation + { + get { return BackingStore?.Get("accommodation"); } + set { BackingStore?.Set("accommodation", value); } + } + + /// The excursions property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToManyExcursionInRequest? Excursions + { + get { return BackingStore?.Get("excursions"); } + set { BackingStore?.Set("excursions", value); } + } + + /// The transport property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.NullableToOneTransportInRequest? Transport + { + get { return BackingStore?.Get("transport"); } + set { BackingStore?.Set("transport", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInCreateVacationRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInCreateVacationRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "accommodation", n => { Accommodation = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToOneAccommodationInRequest.CreateFromDiscriminatorValue); } }, + { "excursions", n => { Excursions = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToManyExcursionInRequest.CreateFromDiscriminatorValue); } }, + { "transport", n => { Transport = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.NullableToOneTransportInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("accommodation", Accommodation); + writer.WriteObjectValue("excursions", Excursions); + writer.WriteObjectValue("transport", Transport); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/RelationshipsInResponse.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/RelationshipsInResponse.cs new file mode 100644 index 0000000000..aff2fbf974 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/RelationshipsInResponse.cs @@ -0,0 +1,75 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "vacations" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInVacationResponse(), + _ => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/RelationshipsInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/RelationshipsInUpdateRequest.cs new file mode 100644 index 0000000000..c0d40587cc --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/RelationshipsInUpdateRequest.cs @@ -0,0 +1,75 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "vacations" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInUpdateVacationRequest(), + _ => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/RelationshipsInUpdateVacationRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/RelationshipsInUpdateVacationRequest.cs new file mode 100644 index 0000000000..8579e6ef66 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/RelationshipsInUpdateVacationRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateVacationRequest : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The accommodation property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToOneAccommodationInRequest? Accommodation + { + get { return BackingStore?.Get("accommodation"); } + set { BackingStore?.Set("accommodation", value); } + } + + /// The excursions property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToManyExcursionInRequest? Excursions + { + get { return BackingStore?.Get("excursions"); } + set { BackingStore?.Set("excursions", value); } + } + + /// The transport property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.NullableToOneTransportInRequest? Transport + { + get { return BackingStore?.Get("transport"); } + set { BackingStore?.Set("transport", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInUpdateVacationRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInUpdateVacationRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "accommodation", n => { Accommodation = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToOneAccommodationInRequest.CreateFromDiscriminatorValue); } }, + { "excursions", n => { Excursions = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToManyExcursionInRequest.CreateFromDiscriminatorValue); } }, + { "transport", n => { Transport = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.NullableToOneTransportInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("accommodation", Accommodation); + writer.WriteObjectValue("excursions", Excursions); + writer.WriteObjectValue("transport", Transport); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/RelationshipsInVacationResponse.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/RelationshipsInVacationResponse.cs new file mode 100644 index 0000000000..180d1aab6c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/RelationshipsInVacationResponse.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInVacationResponse : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// The accommodation property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToOneAccommodationInResponse? Accommodation + { + get { return BackingStore?.Get("accommodation"); } + set { BackingStore?.Set("accommodation", value); } + } + + /// The excursions property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToManyExcursionInResponse? Excursions + { + get { return BackingStore?.Get("excursions"); } + set { BackingStore?.Set("excursions", value); } + } + + /// The transport property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.NullableToOneTransportInResponse? Transport + { + get { return BackingStore?.Get("transport"); } + set { BackingStore?.Set("transport", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInVacationResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipsInVacationResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "accommodation", n => { Accommodation = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToOneAccommodationInResponse.CreateFromDiscriminatorValue); } }, + { "excursions", n => { Excursions = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToManyExcursionInResponse.CreateFromDiscriminatorValue); } }, + { "transport", n => { Transport = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.NullableToOneTransportInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("accommodation", Accommodation); + writer.WriteObjectValue("excursions", Excursions); + writer.WriteObjectValue("transport", Transport); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceCollectionTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceCollectionTopLevelLinks.cs new file mode 100644 index 0000000000..505b2ff55c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceCollectionTopLevelLinks.cs @@ -0,0 +1,115 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceCollectionTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The first property + public string? First + { + get { return BackingStore?.Get("first"); } + set { BackingStore?.Set("first", value); } + } + + /// The last property + public string? Last + { + get { return BackingStore?.Get("last"); } + set { BackingStore?.Set("last", value); } + } + + /// The next property + public string? Next + { + get { return BackingStore?.Get("next"); } + set { BackingStore?.Set("next", value); } + } + + /// The prev property + public string? Prev + { + get { return BackingStore?.Get("prev"); } + set { BackingStore?.Set("prev", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceCollectionTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceCollectionTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceCollectionTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "first", n => { First = n.GetStringValue(); } }, + { "last", n => { Last = n.GetStringValue(); } }, + { "next", n => { Next = n.GetStringValue(); } }, + { "prev", n => { Prev = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("first", First); + writer.WriteStringValue("last", Last); + writer.WriteStringValue("next", Next); + writer.WriteStringValue("prev", Prev); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs new file mode 100644 index 0000000000..a12fa51b7c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs @@ -0,0 +1,124 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceIdentifierCollectionTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The first property + public string? First + { + get { return BackingStore?.Get("first"); } + set { BackingStore?.Set("first", value); } + } + + /// The last property + public string? Last + { + get { return BackingStore?.Get("last"); } + set { BackingStore?.Set("last", value); } + } + + /// The next property + public string? Next + { + get { return BackingStore?.Get("next"); } + set { BackingStore?.Set("next", value); } + } + + /// The prev property + public string? Prev + { + get { return BackingStore?.Get("prev"); } + set { BackingStore?.Set("prev", value); } + } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceIdentifierCollectionTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "first", n => { First = n.GetStringValue(); } }, + { "last", n => { Last = n.GetStringValue(); } }, + { "next", n => { Next = n.GetStringValue(); } }, + { "prev", n => { Prev = n.GetStringValue(); } }, + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("first", First); + writer.WriteStringValue("last", Last); + writer.WriteStringValue("next", Next); + writer.WriteStringValue("prev", Prev); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceIdentifierTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceIdentifierTopLevelLinks.cs new file mode 100644 index 0000000000..52531aeba7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceIdentifierTopLevelLinks.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceIdentifierTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceIdentifierTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceIdentifierTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceIdentifierTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceInCreateRequest.cs new file mode 100644 index 0000000000..006c636142 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceInCreateRequest.cs @@ -0,0 +1,87 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "accommodations" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInCreateAccommodationRequest(), + "excursions" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInCreateExcursionRequest(), + "transports" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInCreateTransportRequest(), + "vacations" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInCreateVacationRequest(), + _ => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceInResponse.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceInResponse.cs new file mode 100644 index 0000000000..ef0edc7b11 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceInResponse.cs @@ -0,0 +1,87 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "accommodations" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInAccommodationResponse(), + "excursions" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInExcursionResponse(), + "transports" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInTransportResponse(), + "vacations" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInVacationResponse(), + _ => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceInUpdateRequest.cs new file mode 100644 index 0000000000..d216bc05c3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceInUpdateRequest.cs @@ -0,0 +1,87 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "accommodations" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInUpdateAccommodationRequest(), + "excursions" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInUpdateExcursionRequest(), + "transports" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInUpdateTransportRequest(), + "vacations" => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInUpdateVacationRequest(), + _ => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceLinks.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceLinks.cs new file mode 100644 index 0000000000..e183a6abda --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceLinks.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceTopLevelLinks.cs new file mode 100644 index 0000000000..c9fb943220 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceType.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceType.cs new file mode 100644 index 0000000000..29f2e160c0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ResourceType.cs @@ -0,0 +1,30 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum ResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "accommodations")] + #pragma warning disable CS1591 + Accommodations, + #pragma warning restore CS1591 + [EnumMember(Value = "excursions")] + #pragma warning disable CS1591 + Excursions, + #pragma warning restore CS1591 + [EnumMember(Value = "transports")] + #pragma warning disable CS1591 + Transports, + #pragma warning restore CS1591 + [EnumMember(Value = "vacations")] + #pragma warning disable CS1591 + Vacations, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/SecondaryAccommodationResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/SecondaryAccommodationResponseDocument.cs new file mode 100644 index 0000000000..7275a54806 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/SecondaryAccommodationResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class SecondaryAccommodationResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInAccommodationResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public SecondaryAccommodationResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.SecondaryAccommodationResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.SecondaryAccommodationResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInAccommodationResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ToManyExcursionInRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ToManyExcursionInRequest.cs new file mode 100644 index 0000000000..bddbf36b25 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ToManyExcursionInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyExcursionInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyExcursionInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToManyExcursionInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToManyExcursionInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ExcursionIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ToManyExcursionInResponse.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ToManyExcursionInResponse.cs new file mode 100644 index 0000000000..6f7f34c3c3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ToManyExcursionInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyExcursionInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyExcursionInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToManyExcursionInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToManyExcursionInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ExcursionIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ToOneAccommodationInRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ToOneAccommodationInRequest.cs new file mode 100644 index 0000000000..83491df0a3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ToOneAccommodationInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToOneAccommodationInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AccommodationIdentifierInRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToOneAccommodationInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToOneAccommodationInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToOneAccommodationInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AccommodationIdentifierInRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ToOneAccommodationInResponse.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ToOneAccommodationInResponse.cs new file mode 100644 index 0000000000..49ca70655a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/ToOneAccommodationInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToOneAccommodationInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AccommodationIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToOneAccommodationInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToOneAccommodationInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToOneAccommodationInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AccommodationIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/TransportCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/TransportCollectionResponseDocument.cs new file mode 100644 index 0000000000..7110d5b545 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/TransportCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class TransportCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public TransportCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.TransportCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.TransportCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInTransportResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/TransportIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/TransportIdentifierInRequest.cs new file mode 100644 index 0000000000..7f03dfd042 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/TransportIdentifierInRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class TransportIdentifierInRequest : global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.TransportIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.TransportIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/TransportIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/TransportIdentifierInResponse.cs new file mode 100644 index 0000000000..4b0075da35 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/TransportIdentifierInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class TransportIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.TransportResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public TransportIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.TransportIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.TransportIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/TransportResourceType.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/TransportResourceType.cs new file mode 100644 index 0000000000..4e241e7587 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/TransportResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum TransportResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "transports")] + #pragma warning disable CS1591 + Transports, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/UpdateAccommodationRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/UpdateAccommodationRequestDocument.cs new file mode 100644 index 0000000000..d83d3035b0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/UpdateAccommodationRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateAccommodationRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInUpdateAccommodationRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateAccommodationRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.UpdateAccommodationRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.UpdateAccommodationRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInUpdateAccommodationRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/UpdateExcursionRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/UpdateExcursionRequestDocument.cs new file mode 100644 index 0000000000..9d538a72ec --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/UpdateExcursionRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateExcursionRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInUpdateExcursionRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateExcursionRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.UpdateExcursionRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.UpdateExcursionRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInUpdateExcursionRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/UpdateTransportRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/UpdateTransportRequestDocument.cs new file mode 100644 index 0000000000..f71ccaa8a5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/UpdateTransportRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateTransportRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInUpdateTransportRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateTransportRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.UpdateTransportRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.UpdateTransportRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInUpdateTransportRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/UpdateVacationRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/UpdateVacationRequestDocument.cs new file mode 100644 index 0000000000..b579eb69af --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/UpdateVacationRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateVacationRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInUpdateVacationRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateVacationRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.UpdateVacationRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.UpdateVacationRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInUpdateVacationRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/VacationCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/VacationCollectionResponseDocument.cs new file mode 100644 index 0000000000..60112bb059 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Models/VacationCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class VacationCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public VacationCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.VacationCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.VacationCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.DataInVacationResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Transports/Item/TransportsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Transports/Item/TransportsItemRequestBuilder.cs new file mode 100644 index 0000000000..0929e31a11 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Transports/Item/TransportsItemRequestBuilder.cs @@ -0,0 +1,209 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Transports.Item +{ + /// + /// Builds and executes requests for operations under \transports\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TransportsItemRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public TransportsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/transports/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public TransportsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/transports/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing transport by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual transport by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.PrimaryTransportResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing transport. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.UpdateTransportRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.PrimaryTransportResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing transport by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual transport by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing transport. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.UpdateTransportRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Transports.Item.TransportsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Transports.Item.TransportsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual transport by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TransportsItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TransportsItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing transport. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TransportsItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Transports/TransportsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Transports/TransportsRequestBuilder.cs new file mode 100644 index 0000000000..d2842e63e3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Transports/TransportsRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Transports.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Transports +{ + /// + /// Builds and executes requests for operations under \transports + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TransportsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.Links.GeneratedCode.transports.item collection + /// The identifier of the transport to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Transports.Item.TransportsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Transports.Item.TransportsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public TransportsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/transports{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public TransportsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/transports{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of transports. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.TransportCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new transport. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.CreateTransportRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.PrimaryTransportResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of transports. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new transport. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.CreateTransportRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Transports.TransportsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Transports.TransportsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of transports. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TransportsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TransportsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new transport. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TransportsRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/Accommodation/AccommodationRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/Accommodation/AccommodationRequestBuilder.cs new file mode 100644 index 0000000000..9927c18cdb --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/Accommodation/AccommodationRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Accommodation +{ + /// + /// Builds and executes requests for operations under \vacations\{id}\accommodation + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AccommodationRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public AccommodationRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/vacations/{id}/accommodation{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public AccommodationRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/vacations/{id}/accommodation{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related accommodation of an individual vacation's accommodation relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.SecondaryAccommodationResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related accommodation of an individual vacation's accommodation relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Accommodation.AccommodationRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Accommodation.AccommodationRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related accommodation of an individual vacation's accommodation relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AccommodationRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AccommodationRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/Excursions/ExcursionsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/Excursions/ExcursionsRequestBuilder.cs new file mode 100644 index 0000000000..66cb804749 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/Excursions/ExcursionsRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Excursions +{ + /// + /// Builds and executes requests for operations under \vacations\{id}\excursions + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ExcursionsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ExcursionsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/vacations/{id}/excursions{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ExcursionsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/vacations/{id}/excursions{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related excursions of an individual vacation's excursions relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ExcursionCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related excursions of an individual vacation's excursions relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Excursions.ExcursionsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Excursions.ExcursionsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related excursions of an individual vacation's excursions relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ExcursionsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ExcursionsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/Relationships/Accommodation/AccommodationRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/Relationships/Accommodation/AccommodationRequestBuilder.cs new file mode 100644 index 0000000000..f6099731e7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/Relationships/Accommodation/AccommodationRequestBuilder.cs @@ -0,0 +1,168 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Relationships.Accommodation +{ + /// + /// Builds and executes requests for operations under \vacations\{id}\relationships\accommodation + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AccommodationRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public AccommodationRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/vacations/{id}/relationships/accommodation{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public AccommodationRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/vacations/{id}/relationships/accommodation{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related accommodation identity of an individual vacation's accommodation relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.AccommodationIdentifierResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns an existing accommodation to the accommodation relationship of an individual vacation. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToOneAccommodationInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related accommodation identity of an individual vacation's accommodation relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns an existing accommodation to the accommodation relationship of an individual vacation. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToOneAccommodationInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Relationships.Accommodation.AccommodationRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Relationships.Accommodation.AccommodationRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related accommodation identity of an individual vacation's accommodation relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AccommodationRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AccommodationRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/Relationships/Excursions/ExcursionsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/Relationships/Excursions/ExcursionsRequestBuilder.cs new file mode 100644 index 0000000000..e97a234f4a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/Relationships/Excursions/ExcursionsRequestBuilder.cs @@ -0,0 +1,248 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Relationships.Excursions +{ + /// + /// Builds and executes requests for operations under \vacations\{id}\relationships\excursions + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ExcursionsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ExcursionsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/vacations/{id}/relationships/excursions{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ExcursionsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/vacations/{id}/relationships/excursions{?query*}", rawUrl) + { + } + + /// + /// Removes existing excursions from the excursions relationship of an individual vacation. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task DeleteAsync(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToManyExcursionInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToDeleteRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related excursion identities of an individual vacation's excursions relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ExcursionIdentifierCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns existing excursions to the excursions relationship of an individual vacation. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToManyExcursionInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Adds existing excursions to the excursions relationship of an individual vacation. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToManyExcursionInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Removes existing excursions from the excursions relationship of an individual vacation. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToManyExcursionInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Retrieves the related excursion identities of an individual vacation's excursions relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns existing excursions to the excursions relationship of an individual vacation. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToManyExcursionInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Adds existing excursions to the excursions relationship of an individual vacation. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ToManyExcursionInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Relationships.Excursions.ExcursionsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Relationships.Excursions.ExcursionsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related excursion identities of an individual vacation's excursions relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ExcursionsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ExcursionsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..1ea9cf33ae --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Relationships.Accommodation; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Relationships.Excursions; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Relationships.Transport; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \vacations\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The accommodation property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Relationships.Accommodation.AccommodationRequestBuilder Accommodation + { + get => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Relationships.Accommodation.AccommodationRequestBuilder(PathParameters, RequestAdapter); + } + + /// The excursions property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Relationships.Excursions.ExcursionsRequestBuilder Excursions + { + get => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Relationships.Excursions.ExcursionsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The transport property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Relationships.Transport.TransportRequestBuilder Transport + { + get => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Relationships.Transport.TransportRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/vacations/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/vacations/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/Relationships/Transport/TransportRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/Relationships/Transport/TransportRequestBuilder.cs new file mode 100644 index 0000000000..943abb0242 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/Relationships/Transport/TransportRequestBuilder.cs @@ -0,0 +1,168 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Relationships.Transport +{ + /// + /// Builds and executes requests for operations under \vacations\{id}\relationships\transport + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TransportRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public TransportRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/vacations/{id}/relationships/transport{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public TransportRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/vacations/{id}/relationships/transport{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related transport identity of an individual vacation's transport relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.NullableTransportIdentifierResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Clears or assigns an existing transport to the transport relationship of an individual vacation. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.NullableToOneTransportInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related transport identity of an individual vacation's transport relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Clears or assigns an existing transport to the transport relationship of an individual vacation. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.NullableToOneTransportInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Relationships.Transport.TransportRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Relationships.Transport.TransportRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related transport identity of an individual vacation's transport relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TransportRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TransportRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/Transport/TransportRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/Transport/TransportRequestBuilder.cs new file mode 100644 index 0000000000..1556b9733b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/Transport/TransportRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Transport +{ + /// + /// Builds and executes requests for operations under \vacations\{id}\transport + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TransportRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public TransportRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/vacations/{id}/transport{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public TransportRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/vacations/{id}/transport{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related transport of an individual vacation's transport relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.NullableSecondaryTransportResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related transport of an individual vacation's transport relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Transport.TransportRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Transport.TransportRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related transport of an individual vacation's transport relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TransportRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class TransportRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/VacationsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/VacationsItemRequestBuilder.cs new file mode 100644 index 0000000000..a487b7f64c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/Item/VacationsItemRequestBuilder.cs @@ -0,0 +1,237 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Accommodation; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Excursions; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Relationships; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Transport; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item +{ + /// + /// Builds and executes requests for operations under \vacations\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class VacationsItemRequestBuilder : BaseRequestBuilder + { + /// The accommodation property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Accommodation.AccommodationRequestBuilder Accommodation + { + get => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Accommodation.AccommodationRequestBuilder(PathParameters, RequestAdapter); + } + + /// The excursions property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Excursions.ExcursionsRequestBuilder Excursions + { + get => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Excursions.ExcursionsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The transport property + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Transport.TransportRequestBuilder Transport + { + get => new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.Transport.TransportRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public VacationsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/vacations/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public VacationsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/vacations/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing vacation by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual vacation by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.PrimaryVacationResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing vacation. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.UpdateVacationRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.PrimaryVacationResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing vacation by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual vacation by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing vacation. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.UpdateVacationRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.VacationsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.VacationsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual vacation by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class VacationsItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class VacationsItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing vacation. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class VacationsItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/VacationsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/VacationsRequestBuilder.cs new file mode 100644 index 0000000000..358bd9814e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/Vacations/VacationsRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models; +using OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations +{ + /// + /// Builds and executes requests for operations under \vacations + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class VacationsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.Links.GeneratedCode.vacations.item collection + /// The identifier of the vacation to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.VacationsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.Item.VacationsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public VacationsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/vacations{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public VacationsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/vacations{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of vacations. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.VacationCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new vacation. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.CreateVacationRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.PrimaryVacationResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of vacations. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new vacation. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Models.CreateVacationRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.VacationsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.Links.GeneratedCode.Vacations.VacationsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of vacations. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class VacationsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class VacationsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new vacation. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class VacationsRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/ModelStateValidationClient.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/ModelStateValidationClient.cs new file mode 100644 index 0000000000..79e12b6fd0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/ModelStateValidationClient.cs @@ -0,0 +1,54 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using Microsoft.Kiota.Serialization.Form; +using Microsoft.Kiota.Serialization.Json; +using Microsoft.Kiota.Serialization.Multipart; +using Microsoft.Kiota.Serialization.Text; +using OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.SocialMediaAccounts; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode +{ + /// + /// The main entry point of the SDK, exposes the configuration and the fluent API. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ModelStateValidationClient : BaseRequestBuilder + { + /// The socialMediaAccounts property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.SocialMediaAccounts.SocialMediaAccountsRequestBuilder SocialMediaAccounts + { + get => new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.SocialMediaAccounts.SocialMediaAccountsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The backing store to use for the models. + /// The request adapter to use to execute the requests. + public ModelStateValidationClient(IRequestAdapter requestAdapter, IBackingStoreFactory backingStore = default) : base(requestAdapter, "{+baseurl}", new Dictionary()) + { + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + if (string.IsNullOrEmpty(RequestAdapter.BaseUrl)) + { + RequestAdapter.BaseUrl = "http://localhost"; + } + PathParameters.TryAdd("baseurl", RequestAdapter.BaseUrl); + RequestAdapter.EnableBackingStore(backingStore); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/AttributesInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/AttributesInCreateRequest.cs new file mode 100644 index 0000000000..16db047270 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/AttributesInCreateRequest.cs @@ -0,0 +1,75 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "socialMediaAccounts" => new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInCreateSocialMediaAccountRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/AttributesInCreateSocialMediaAccountRequest.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/AttributesInCreateSocialMediaAccountRequest.cs new file mode 100644 index 0000000000..1180b1d39a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/AttributesInCreateSocialMediaAccountRequest.cs @@ -0,0 +1,213 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateSocialMediaAccountRequest : global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The age property + public double? Age + { + get { return BackingStore?.Get("age"); } + set { BackingStore?.Set("age", value); } + } + + /// The alternativeId property + public Guid? AlternativeId + { + get { return BackingStore?.Get("alternativeId"); } + set { BackingStore?.Set("alternativeId", value); } + } + + /// The backgroundPicture property + public string? BackgroundPicture + { + get { return BackingStore?.Get("backgroundPicture"); } + set { BackingStore?.Set("backgroundPicture", value); } + } + + /// The countryCode property + public string? CountryCode + { + get { return BackingStore?.Get("countryCode"); } + set { BackingStore?.Set("countryCode", value); } + } + + /// The creditCard property + public string? CreditCard + { + get { return BackingStore?.Get("creditCard"); } + set { BackingStore?.Set("creditCard", value); } + } + + /// The email property + public string? Email + { + get { return BackingStore?.Get("email"); } + set { BackingStore?.Set("email", value); } + } + + /// The firstName property + public string? FirstName + { + get { return BackingStore?.Get("firstName"); } + set { BackingStore?.Set("firstName", value); } + } + + /// The lastName property + public string? LastName + { + get { return BackingStore?.Get("lastName"); } + set { BackingStore?.Set("lastName", value); } + } + + /// The nextRevalidation property + public string? NextRevalidation + { + get { return BackingStore?.Get("nextRevalidation"); } + set { BackingStore?.Set("nextRevalidation", value); } + } + + /// The password property + public byte[]? Password + { + get { return BackingStore?.Get("password"); } + set { BackingStore?.Set("password", value); } + } + + /// The phone property + public string? Phone + { + get { return BackingStore?.Get("phone"); } + set { BackingStore?.Set("phone", value); } + } + + /// The planet property + public string? Planet + { + get { return BackingStore?.Get("planet"); } + set { BackingStore?.Set("planet", value); } + } + + /// The profilePicture property + public string? ProfilePicture + { + get { return BackingStore?.Get("profilePicture"); } + set { BackingStore?.Set("profilePicture", value); } + } + + /// The tags property + public List? Tags + { + get { return BackingStore?.Get?>("tags"); } + set { BackingStore?.Set("tags", value); } + } + + /// The userName property + public string? UserName + { + get { return BackingStore?.Get("userName"); } + set { BackingStore?.Set("userName", value); } + } + + /// The validatedAt property + public DateTimeOffset? ValidatedAt + { + get { return BackingStore?.Get("validatedAt"); } + set { BackingStore?.Set("validatedAt", value); } + } + + /// The validatedAtDate property + public Date? ValidatedAtDate + { + get { return BackingStore?.Get("validatedAtDate"); } + set { BackingStore?.Set("validatedAtDate", value); } + } + + /// The validatedAtTime property + public Time? ValidatedAtTime + { + get { return BackingStore?.Get("validatedAtTime"); } + set { BackingStore?.Set("validatedAtTime", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInCreateSocialMediaAccountRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInCreateSocialMediaAccountRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "age", n => { Age = n.GetDoubleValue(); } }, + { "alternativeId", n => { AlternativeId = n.GetGuidValue(); } }, + { "backgroundPicture", n => { BackgroundPicture = n.GetStringValue(); } }, + { "countryCode", n => { CountryCode = n.GetStringValue(); } }, + { "creditCard", n => { CreditCard = n.GetStringValue(); } }, + { "email", n => { Email = n.GetStringValue(); } }, + { "firstName", n => { FirstName = n.GetStringValue(); } }, + { "lastName", n => { LastName = n.GetStringValue(); } }, + { "nextRevalidation", n => { NextRevalidation = n.GetStringValue(); } }, + { "password", n => { Password = n.GetByteArrayValue(); } }, + { "phone", n => { Phone = n.GetStringValue(); } }, + { "planet", n => { Planet = n.GetStringValue(); } }, + { "profilePicture", n => { ProfilePicture = n.GetStringValue(); } }, + { "tags", n => { Tags = n.GetCollectionOfPrimitiveValues()?.AsList(); } }, + { "userName", n => { UserName = n.GetStringValue(); } }, + { "validatedAt", n => { ValidatedAt = n.GetDateTimeOffsetValue(); } }, + { "validatedAtDate", n => { ValidatedAtDate = n.GetDateValue(); } }, + { "validatedAtTime", n => { ValidatedAtTime = n.GetTimeValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteDoubleValue("age", Age); + writer.WriteGuidValue("alternativeId", AlternativeId); + writer.WriteStringValue("backgroundPicture", BackgroundPicture); + writer.WriteStringValue("countryCode", CountryCode); + writer.WriteStringValue("creditCard", CreditCard); + writer.WriteStringValue("email", Email); + writer.WriteStringValue("firstName", FirstName); + writer.WriteStringValue("lastName", LastName); + writer.WriteStringValue("nextRevalidation", NextRevalidation); + writer.WriteByteArrayValue("password", Password); + writer.WriteStringValue("phone", Phone); + writer.WriteStringValue("planet", Planet); + writer.WriteStringValue("profilePicture", ProfilePicture); + writer.WriteCollectionOfPrimitiveValues("tags", Tags); + writer.WriteStringValue("userName", UserName); + writer.WriteDateTimeOffsetValue("validatedAt", ValidatedAt); + writer.WriteDateValue("validatedAtDate", ValidatedAtDate); + writer.WriteTimeValue("validatedAtTime", ValidatedAtTime); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/AttributesInResponse.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/AttributesInResponse.cs new file mode 100644 index 0000000000..40ca9d3903 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/AttributesInResponse.cs @@ -0,0 +1,75 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "socialMediaAccounts" => new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInSocialMediaAccountResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/AttributesInSocialMediaAccountResponse.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/AttributesInSocialMediaAccountResponse.cs new file mode 100644 index 0000000000..68dee62e83 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/AttributesInSocialMediaAccountResponse.cs @@ -0,0 +1,213 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInSocialMediaAccountResponse : global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The age property + public double? Age + { + get { return BackingStore?.Get("age"); } + set { BackingStore?.Set("age", value); } + } + + /// The alternativeId property + public Guid? AlternativeId + { + get { return BackingStore?.Get("alternativeId"); } + set { BackingStore?.Set("alternativeId", value); } + } + + /// The backgroundPicture property + public string? BackgroundPicture + { + get { return BackingStore?.Get("backgroundPicture"); } + set { BackingStore?.Set("backgroundPicture", value); } + } + + /// The countryCode property + public string? CountryCode + { + get { return BackingStore?.Get("countryCode"); } + set { BackingStore?.Set("countryCode", value); } + } + + /// The creditCard property + public string? CreditCard + { + get { return BackingStore?.Get("creditCard"); } + set { BackingStore?.Set("creditCard", value); } + } + + /// The email property + public string? Email + { + get { return BackingStore?.Get("email"); } + set { BackingStore?.Set("email", value); } + } + + /// The firstName property + public string? FirstName + { + get { return BackingStore?.Get("firstName"); } + set { BackingStore?.Set("firstName", value); } + } + + /// The lastName property + public string? LastName + { + get { return BackingStore?.Get("lastName"); } + set { BackingStore?.Set("lastName", value); } + } + + /// The nextRevalidation property + public string? NextRevalidation + { + get { return BackingStore?.Get("nextRevalidation"); } + set { BackingStore?.Set("nextRevalidation", value); } + } + + /// The password property + public byte[]? Password + { + get { return BackingStore?.Get("password"); } + set { BackingStore?.Set("password", value); } + } + + /// The phone property + public string? Phone + { + get { return BackingStore?.Get("phone"); } + set { BackingStore?.Set("phone", value); } + } + + /// The planet property + public string? Planet + { + get { return BackingStore?.Get("planet"); } + set { BackingStore?.Set("planet", value); } + } + + /// The profilePicture property + public string? ProfilePicture + { + get { return BackingStore?.Get("profilePicture"); } + set { BackingStore?.Set("profilePicture", value); } + } + + /// The tags property + public List? Tags + { + get { return BackingStore?.Get?>("tags"); } + set { BackingStore?.Set("tags", value); } + } + + /// The userName property + public string? UserName + { + get { return BackingStore?.Get("userName"); } + set { BackingStore?.Set("userName", value); } + } + + /// The validatedAt property + public DateTimeOffset? ValidatedAt + { + get { return BackingStore?.Get("validatedAt"); } + set { BackingStore?.Set("validatedAt", value); } + } + + /// The validatedAtDate property + public Date? ValidatedAtDate + { + get { return BackingStore?.Get("validatedAtDate"); } + set { BackingStore?.Set("validatedAtDate", value); } + } + + /// The validatedAtTime property + public Time? ValidatedAtTime + { + get { return BackingStore?.Get("validatedAtTime"); } + set { BackingStore?.Set("validatedAtTime", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInSocialMediaAccountResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInSocialMediaAccountResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "age", n => { Age = n.GetDoubleValue(); } }, + { "alternativeId", n => { AlternativeId = n.GetGuidValue(); } }, + { "backgroundPicture", n => { BackgroundPicture = n.GetStringValue(); } }, + { "countryCode", n => { CountryCode = n.GetStringValue(); } }, + { "creditCard", n => { CreditCard = n.GetStringValue(); } }, + { "email", n => { Email = n.GetStringValue(); } }, + { "firstName", n => { FirstName = n.GetStringValue(); } }, + { "lastName", n => { LastName = n.GetStringValue(); } }, + { "nextRevalidation", n => { NextRevalidation = n.GetStringValue(); } }, + { "password", n => { Password = n.GetByteArrayValue(); } }, + { "phone", n => { Phone = n.GetStringValue(); } }, + { "planet", n => { Planet = n.GetStringValue(); } }, + { "profilePicture", n => { ProfilePicture = n.GetStringValue(); } }, + { "tags", n => { Tags = n.GetCollectionOfPrimitiveValues()?.AsList(); } }, + { "userName", n => { UserName = n.GetStringValue(); } }, + { "validatedAt", n => { ValidatedAt = n.GetDateTimeOffsetValue(); } }, + { "validatedAtDate", n => { ValidatedAtDate = n.GetDateValue(); } }, + { "validatedAtTime", n => { ValidatedAtTime = n.GetTimeValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteDoubleValue("age", Age); + writer.WriteGuidValue("alternativeId", AlternativeId); + writer.WriteStringValue("backgroundPicture", BackgroundPicture); + writer.WriteStringValue("countryCode", CountryCode); + writer.WriteStringValue("creditCard", CreditCard); + writer.WriteStringValue("email", Email); + writer.WriteStringValue("firstName", FirstName); + writer.WriteStringValue("lastName", LastName); + writer.WriteStringValue("nextRevalidation", NextRevalidation); + writer.WriteByteArrayValue("password", Password); + writer.WriteStringValue("phone", Phone); + writer.WriteStringValue("planet", Planet); + writer.WriteStringValue("profilePicture", ProfilePicture); + writer.WriteCollectionOfPrimitiveValues("tags", Tags); + writer.WriteStringValue("userName", UserName); + writer.WriteDateTimeOffsetValue("validatedAt", ValidatedAt); + writer.WriteDateValue("validatedAtDate", ValidatedAtDate); + writer.WriteTimeValue("validatedAtTime", ValidatedAtTime); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/AttributesInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/AttributesInUpdateRequest.cs new file mode 100644 index 0000000000..1458bf604b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/AttributesInUpdateRequest.cs @@ -0,0 +1,75 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "socialMediaAccounts" => new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInUpdateSocialMediaAccountRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/AttributesInUpdateSocialMediaAccountRequest.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/AttributesInUpdateSocialMediaAccountRequest.cs new file mode 100644 index 0000000000..76e7aead9a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/AttributesInUpdateSocialMediaAccountRequest.cs @@ -0,0 +1,213 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateSocialMediaAccountRequest : global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The age property + public double? Age + { + get { return BackingStore?.Get("age"); } + set { BackingStore?.Set("age", value); } + } + + /// The alternativeId property + public Guid? AlternativeId + { + get { return BackingStore?.Get("alternativeId"); } + set { BackingStore?.Set("alternativeId", value); } + } + + /// The backgroundPicture property + public string? BackgroundPicture + { + get { return BackingStore?.Get("backgroundPicture"); } + set { BackingStore?.Set("backgroundPicture", value); } + } + + /// The countryCode property + public string? CountryCode + { + get { return BackingStore?.Get("countryCode"); } + set { BackingStore?.Set("countryCode", value); } + } + + /// The creditCard property + public string? CreditCard + { + get { return BackingStore?.Get("creditCard"); } + set { BackingStore?.Set("creditCard", value); } + } + + /// The email property + public string? Email + { + get { return BackingStore?.Get("email"); } + set { BackingStore?.Set("email", value); } + } + + /// The firstName property + public string? FirstName + { + get { return BackingStore?.Get("firstName"); } + set { BackingStore?.Set("firstName", value); } + } + + /// The lastName property + public string? LastName + { + get { return BackingStore?.Get("lastName"); } + set { BackingStore?.Set("lastName", value); } + } + + /// The nextRevalidation property + public string? NextRevalidation + { + get { return BackingStore?.Get("nextRevalidation"); } + set { BackingStore?.Set("nextRevalidation", value); } + } + + /// The password property + public byte[]? Password + { + get { return BackingStore?.Get("password"); } + set { BackingStore?.Set("password", value); } + } + + /// The phone property + public string? Phone + { + get { return BackingStore?.Get("phone"); } + set { BackingStore?.Set("phone", value); } + } + + /// The planet property + public string? Planet + { + get { return BackingStore?.Get("planet"); } + set { BackingStore?.Set("planet", value); } + } + + /// The profilePicture property + public string? ProfilePicture + { + get { return BackingStore?.Get("profilePicture"); } + set { BackingStore?.Set("profilePicture", value); } + } + + /// The tags property + public List? Tags + { + get { return BackingStore?.Get?>("tags"); } + set { BackingStore?.Set("tags", value); } + } + + /// The userName property + public string? UserName + { + get { return BackingStore?.Get("userName"); } + set { BackingStore?.Set("userName", value); } + } + + /// The validatedAt property + public DateTimeOffset? ValidatedAt + { + get { return BackingStore?.Get("validatedAt"); } + set { BackingStore?.Set("validatedAt", value); } + } + + /// The validatedAtDate property + public Date? ValidatedAtDate + { + get { return BackingStore?.Get("validatedAtDate"); } + set { BackingStore?.Set("validatedAtDate", value); } + } + + /// The validatedAtTime property + public Time? ValidatedAtTime + { + get { return BackingStore?.Get("validatedAtTime"); } + set { BackingStore?.Set("validatedAtTime", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInUpdateSocialMediaAccountRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInUpdateSocialMediaAccountRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "age", n => { Age = n.GetDoubleValue(); } }, + { "alternativeId", n => { AlternativeId = n.GetGuidValue(); } }, + { "backgroundPicture", n => { BackgroundPicture = n.GetStringValue(); } }, + { "countryCode", n => { CountryCode = n.GetStringValue(); } }, + { "creditCard", n => { CreditCard = n.GetStringValue(); } }, + { "email", n => { Email = n.GetStringValue(); } }, + { "firstName", n => { FirstName = n.GetStringValue(); } }, + { "lastName", n => { LastName = n.GetStringValue(); } }, + { "nextRevalidation", n => { NextRevalidation = n.GetStringValue(); } }, + { "password", n => { Password = n.GetByteArrayValue(); } }, + { "phone", n => { Phone = n.GetStringValue(); } }, + { "planet", n => { Planet = n.GetStringValue(); } }, + { "profilePicture", n => { ProfilePicture = n.GetStringValue(); } }, + { "tags", n => { Tags = n.GetCollectionOfPrimitiveValues()?.AsList(); } }, + { "userName", n => { UserName = n.GetStringValue(); } }, + { "validatedAt", n => { ValidatedAt = n.GetDateTimeOffsetValue(); } }, + { "validatedAtDate", n => { ValidatedAtDate = n.GetDateValue(); } }, + { "validatedAtTime", n => { ValidatedAtTime = n.GetTimeValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteDoubleValue("age", Age); + writer.WriteGuidValue("alternativeId", AlternativeId); + writer.WriteStringValue("backgroundPicture", BackgroundPicture); + writer.WriteStringValue("countryCode", CountryCode); + writer.WriteStringValue("creditCard", CreditCard); + writer.WriteStringValue("email", Email); + writer.WriteStringValue("firstName", FirstName); + writer.WriteStringValue("lastName", LastName); + writer.WriteStringValue("nextRevalidation", NextRevalidation); + writer.WriteByteArrayValue("password", Password); + writer.WriteStringValue("phone", Phone); + writer.WriteStringValue("planet", Planet); + writer.WriteStringValue("profilePicture", ProfilePicture); + writer.WriteCollectionOfPrimitiveValues("tags", Tags); + writer.WriteStringValue("userName", UserName); + writer.WriteDateTimeOffsetValue("validatedAt", ValidatedAt); + writer.WriteDateValue("validatedAtDate", ValidatedAtDate); + writer.WriteTimeValue("validatedAtTime", ValidatedAtTime); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/CreateSocialMediaAccountRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/CreateSocialMediaAccountRequestDocument.cs new file mode 100644 index 0000000000..0bc12dfcdb --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/CreateSocialMediaAccountRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateSocialMediaAccountRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.DataInCreateSocialMediaAccountRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateSocialMediaAccountRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.CreateSocialMediaAccountRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.CreateSocialMediaAccountRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.DataInCreateSocialMediaAccountRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/DataInCreateSocialMediaAccountRequest.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/DataInCreateSocialMediaAccountRequest.cs new file mode 100644 index 0000000000..b2a9fe8fc4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/DataInCreateSocialMediaAccountRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateSocialMediaAccountRequest : global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInCreateSocialMediaAccountRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.DataInCreateSocialMediaAccountRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.DataInCreateSocialMediaAccountRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInCreateSocialMediaAccountRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/DataInSocialMediaAccountResponse.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/DataInSocialMediaAccountResponse.cs new file mode 100644 index 0000000000..5d4e2e2249 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/DataInSocialMediaAccountResponse.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInSocialMediaAccountResponse : global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInSocialMediaAccountResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.DataInSocialMediaAccountResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.DataInSocialMediaAccountResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInSocialMediaAccountResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetGuidValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteGuidValue("id", Id); + writer.WriteObjectValue("links", Links); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/DataInUpdateSocialMediaAccountRequest.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/DataInUpdateSocialMediaAccountRequest.cs new file mode 100644 index 0000000000..a42f2f8330 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/DataInUpdateSocialMediaAccountRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateSocialMediaAccountRequest : global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInUpdateSocialMediaAccountRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.DataInUpdateSocialMediaAccountRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.DataInUpdateSocialMediaAccountRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.AttributesInUpdateSocialMediaAccountRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetGuidValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteGuidValue("id", Id); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ErrorLinks.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ErrorLinks.cs new file mode 100644 index 0000000000..962ad2a606 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ErrorLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// The about property + public string? About + { + get { return BackingStore?.Get("about"); } + set { BackingStore?.Set("about", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The type property + public string? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "about", n => { About = n.GetStringValue(); } }, + { "type", n => { Type = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("about", About); + writer.WriteStringValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ErrorObject.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ErrorObject.cs new file mode 100644 index 0000000000..ae0b0f1df6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ErrorObject.cs @@ -0,0 +1,133 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorObject : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The code property + public string? Code + { + get { return BackingStore?.Get("code"); } + set { BackingStore?.Set("code", value); } + } + + /// The detail property + public string? Detail + { + get { return BackingStore?.Get("detail"); } + set { BackingStore?.Set("detail", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The source property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorSource? Source + { + get { return BackingStore?.Get("source"); } + set { BackingStore?.Set("source", value); } + } + + /// The status property + public string? Status + { + get { return BackingStore?.Get("status"); } + set { BackingStore?.Set("status", value); } + } + + /// The title property + public string? Title + { + get { return BackingStore?.Get("title"); } + set { BackingStore?.Set("title", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorObject() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorObject CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorObject(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "code", n => { Code = n.GetStringValue(); } }, + { "detail", n => { Detail = n.GetStringValue(); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "source", n => { Source = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorSource.CreateFromDiscriminatorValue); } }, + { "status", n => { Status = n.GetStringValue(); } }, + { "title", n => { Title = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("code", Code); + writer.WriteStringValue("detail", Detail); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + writer.WriteObjectValue("source", Source); + writer.WriteStringValue("status", Status); + writer.WriteStringValue("title", Title); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ErrorResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ErrorResponseDocument.cs new file mode 100644 index 0000000000..70ecdd4e35 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ErrorResponseDocument.cs @@ -0,0 +1,92 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorResponseDocument : ApiException, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The errors property + public List? Errors + { + get { return BackingStore?.Get?>("errors"); } + set { BackingStore?.Set("errors", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The primary error message. + public override string Message { get => base.Message; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "errors", n => { Errors = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorObject.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("errors", Errors); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ErrorSource.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ErrorSource.cs new file mode 100644 index 0000000000..c5ad075af9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ErrorSource.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorSource : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The header property + public string? Header + { + get { return BackingStore?.Get("header"); } + set { BackingStore?.Set("header", value); } + } + + /// The parameter property + public string? Parameter + { + get { return BackingStore?.Get("parameter"); } + set { BackingStore?.Set("parameter", value); } + } + + /// The pointer property + public string? Pointer + { + get { return BackingStore?.Get("pointer"); } + set { BackingStore?.Set("pointer", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorSource() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorSource CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorSource(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "header", n => { Header = n.GetStringValue(); } }, + { "parameter", n => { Parameter = n.GetStringValue(); } }, + { "pointer", n => { Pointer = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("header", Header); + writer.WriteStringValue("parameter", Parameter); + writer.WriteStringValue("pointer", Pointer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ErrorTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ErrorTopLevelLinks.cs new file mode 100644 index 0000000000..1cfb0ac02b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ErrorTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/Meta.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/Meta.cs new file mode 100644 index 0000000000..0ce479b554 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/Meta.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class Meta : IAdditionalDataHolder, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + public IDictionary AdditionalData + { + get { return BackingStore.Get>("AdditionalData") ?? new Dictionary(); } + set { BackingStore.Set("AdditionalData", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// + /// Instantiates a new and sets the default values. + /// + public Meta() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + AdditionalData = new Dictionary(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.Meta CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.Meta(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteAdditionalData(AdditionalData); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/PrimarySocialMediaAccountResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/PrimarySocialMediaAccountResponseDocument.cs new file mode 100644 index 0000000000..0013b483f6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/PrimarySocialMediaAccountResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimarySocialMediaAccountResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.DataInSocialMediaAccountResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimarySocialMediaAccountResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.PrimarySocialMediaAccountResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.PrimarySocialMediaAccountResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.DataInSocialMediaAccountResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ResourceInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ResourceInCreateRequest.cs new file mode 100644 index 0000000000..442849bb0e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ResourceInCreateRequest.cs @@ -0,0 +1,84 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "socialMediaAccounts" => new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.DataInCreateSocialMediaAccountRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ResourceInResponse.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ResourceInResponse.cs new file mode 100644 index 0000000000..5984a83a76 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ResourceInResponse.cs @@ -0,0 +1,84 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "socialMediaAccounts" => new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.DataInSocialMediaAccountResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ResourceInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ResourceInUpdateRequest.cs new file mode 100644 index 0000000000..5ee530f218 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ResourceInUpdateRequest.cs @@ -0,0 +1,84 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "socialMediaAccounts" => new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.DataInUpdateSocialMediaAccountRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ResourceLinks.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ResourceLinks.cs new file mode 100644 index 0000000000..99aeff08e6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ResourceLinks.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ResourceTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ResourceTopLevelLinks.cs new file mode 100644 index 0000000000..3e05b21d48 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ResourceTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ResourceTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ResourceType.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ResourceType.cs new file mode 100644 index 0000000000..ae70b7cb5d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/ResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum ResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "socialMediaAccounts")] + #pragma warning disable CS1591 + SocialMediaAccounts, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/UpdateSocialMediaAccountRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/UpdateSocialMediaAccountRequestDocument.cs new file mode 100644 index 0000000000..9fe2f9d8ec --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/Models/UpdateSocialMediaAccountRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateSocialMediaAccountRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.DataInUpdateSocialMediaAccountRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateSocialMediaAccountRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.UpdateSocialMediaAccountRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.UpdateSocialMediaAccountRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.DataInUpdateSocialMediaAccountRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/SocialMediaAccounts/Item/SocialMediaAccountsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/SocialMediaAccounts/Item/SocialMediaAccountsItemRequestBuilder.cs new file mode 100644 index 0000000000..ae98f228ee --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/SocialMediaAccounts/Item/SocialMediaAccountsItemRequestBuilder.cs @@ -0,0 +1,103 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.SocialMediaAccounts.Item +{ + /// + /// Builds and executes requests for operations under \socialMediaAccounts\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class SocialMediaAccountsItemRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public SocialMediaAccountsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/socialMediaAccounts/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public SocialMediaAccountsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/socialMediaAccounts/{id}{?query*}", rawUrl) + { + } + + /// + /// Updates an existing socialMediaAccount. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.UpdateSocialMediaAccountRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.PrimarySocialMediaAccountResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing socialMediaAccount. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.UpdateSocialMediaAccountRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.SocialMediaAccounts.Item.SocialMediaAccountsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.SocialMediaAccounts.Item.SocialMediaAccountsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Updates an existing socialMediaAccount. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class SocialMediaAccountsItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/SocialMediaAccounts/SocialMediaAccountsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/SocialMediaAccounts/SocialMediaAccountsRequestBuilder.cs new file mode 100644 index 0000000000..0a35a41272 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/SocialMediaAccounts/SocialMediaAccountsRequestBuilder.cs @@ -0,0 +1,119 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models; +using OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.SocialMediaAccounts.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.SocialMediaAccounts +{ + /// + /// Builds and executes requests for operations under \socialMediaAccounts + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class SocialMediaAccountsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.socialMediaAccounts.item collection + /// The identifier of the socialMediaAccount to update. + /// A + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.SocialMediaAccounts.Item.SocialMediaAccountsItemRequestBuilder this[Guid position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.SocialMediaAccounts.Item.SocialMediaAccountsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public SocialMediaAccountsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/socialMediaAccounts{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public SocialMediaAccountsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/socialMediaAccounts{?query*}", rawUrl) + { + } + + /// + /// Creates a new socialMediaAccount. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.CreateSocialMediaAccountRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.PrimarySocialMediaAccountResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new socialMediaAccount. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models.CreateSocialMediaAccountRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.SocialMediaAccounts.SocialMediaAccountsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.SocialMediaAccounts.SocialMediaAccountsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Creates a new socialMediaAccount. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class SocialMediaAccountsRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/ModelStateValidationTests.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/ModelStateValidationTests.cs new file mode 100644 index 0000000000..5a6022df63 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/ModelStateValidationTests.cs @@ -0,0 +1,566 @@ +using FluentAssertions; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode; +using OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.ModelStateValidation; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; +using IJsonApiOptions = JsonApiDotNetCore.Configuration.IJsonApiOptions; + +namespace OpenApiKiotaEndToEndTests.ModelStateValidation; + +public sealed class ModelStateValidationTests + : IClassFixture, ModelStateValidationDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, ModelStateValidationDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly ModelStateValidationFakers _fakers = new(); + + public ModelStateValidationTests(IntegrationTestContext, ModelStateValidationDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseController(); + + var options = testContext.Factory.Services.GetRequiredService(); + options.SerializerOptions.Converters.Add(new UtcDateTimeJsonConverter()); + } + + [Theory] + [InlineData("a")] + [InlineData("abcdefghijklmnopqrstu")] + public async Task Cannot_exceed_length_constraint(string firstName) + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + ModelStateValidationClient apiClient = new(requestAdapter); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Type = ResourceType.SocialMediaAccounts, + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + FirstName = firstName, + LastName = newAccount.LastName + } + } + }; + + // Act + Func action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync()).Which; + response.Errors.Should().HaveCount(1); + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be("The field FirstName must be a string or collection type with a minimum length of '2' and maximum length of '20'."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/firstName"); + } + + [Theory] + [InlineData("ab")] + [InlineData("abcdefghijklmnopqrs")] + public async Task Cannot_exceed_string_length_constraint(string userName) + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + ModelStateValidationClient apiClient = new(requestAdapter); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Type = ResourceType.SocialMediaAccounts, + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + UserName = userName + } + } + }; + + // Act + Func action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync()).Which; + response.Errors.Should().HaveCount(1); + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be("The field UserName must be a string with a minimum length of 3 and a maximum length of 18."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/userName"); + } + + [Fact] + public async Task Cannot_violate_regular_expression_constraint() + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + ModelStateValidationClient apiClient = new(requestAdapter); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Type = ResourceType.SocialMediaAccounts, + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + UserName = "aB1" + } + } + }; + + // Act + Func action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync()).Which; + response.Errors.Should().HaveCount(1); + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be("Only letters are allowed."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/userName"); + } + + [Fact] + public async Task Cannot_use_invalid_credit_card_number() + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + ModelStateValidationClient apiClient = new(requestAdapter); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Type = ResourceType.SocialMediaAccounts, + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + CreditCard = "123-456" + } + } + }; + + // Act + Func action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync()).Which; + response.Errors.Should().HaveCount(1); + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be("The CreditCard field is not a valid credit card number."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/creditCard"); + } + + [Fact] + public async Task Cannot_use_invalid_email_address() + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + ModelStateValidationClient apiClient = new(requestAdapter); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Type = ResourceType.SocialMediaAccounts, + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + Email = "abc" + } + } + }; + + // Act + Func action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync()).Which; + response.Errors.Should().HaveCount(1); + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be("The Email field is not a valid e-mail address."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/email"); + } + + [Fact] + public async Task Cannot_exceed_min_length_constraint() + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + ModelStateValidationClient apiClient = new(requestAdapter); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Type = ResourceType.SocialMediaAccounts, + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + // Using -3 instead of -1 to compensate for base64 padding. + Password = Enumerable.Repeat((byte)'X', SocialMediaAccount.MinPasswordChars - 3).ToArray() + } + } + }; + + // Act + Func action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync()).Which; + response.Errors.Should().HaveCount(1); + + const int minCharsInBase64 = SocialMediaAccount.MinPasswordCharsInBase64; + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be($"The field Password must be a string or array type with a minimum length of '{minCharsInBase64}'."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/password"); + } + + [Fact] + public async Task Cannot_exceed_max_length_constraint() + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + ModelStateValidationClient apiClient = new(requestAdapter); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Type = ResourceType.SocialMediaAccounts, + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + Password = Enumerable.Repeat((byte)'X', SocialMediaAccount.MaxPasswordChars + 1).ToArray() + } + } + }; + + // Act + Func action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync()).Which; + response.Errors.Should().HaveCount(1); + + const int maxCharsInBase64 = SocialMediaAccount.MaxPasswordCharsInBase64; + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be($"The field Password must be a string or array type with a maximum length of '{maxCharsInBase64}'."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/password"); + } + + [Theory] + [InlineData(-1)] + [InlineData(-0.56)] + [InlineData(123.98)] + [InlineData(124)] + public async Task Cannot_use_double_outside_of_valid_range(double age) + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + ModelStateValidationClient apiClient = new(requestAdapter); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Type = ResourceType.SocialMediaAccounts, + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + Age = age + } + } + }; + + // Act + Func action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync()).Which; + response.Errors.Should().HaveCount(1); + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be($"The field Age must be between {0.1} exclusive and {122.9} exclusive."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/age"); + } + + [Fact] + public async Task Cannot_use_relative_url() + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + ModelStateValidationClient apiClient = new(requestAdapter); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Type = ResourceType.SocialMediaAccounts, + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + BackgroundPicture = "relative-url" + } + } + }; + + // Act + Func action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync()).Which; + response.Errors.Should().HaveCount(1); + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be("The BackgroundPicture field is not a valid fully-qualified http, https, or ftp URL."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/backgroundPicture"); + } + + [Theory] + [InlineData(0)] + [InlineData(11)] + public async Task Cannot_exceed_collection_length_constraint(int length) + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + ModelStateValidationClient apiClient = new(requestAdapter); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Type = ResourceType.SocialMediaAccounts, + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + Tags = Enumerable.Repeat("-", length).ToList() + } + } + }; + + // Act + Func action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync()).Which; + response.Errors.Should().HaveCount(1); + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be("The field Tags must be a string or collection type with a minimum length of '1' and maximum length of '10'."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/tags"); + } + + [Fact] + public async Task Cannot_use_non_allowed_value() + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + ModelStateValidationClient apiClient = new(requestAdapter); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Type = ResourceType.SocialMediaAccounts, + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + CountryCode = "XX" + } + } + }; + + // Act + Func action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync()).Which; + response.Errors.Should().HaveCount(1); + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be("The CountryCode field does not equal any of the values specified in AllowedValuesAttribute."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/countryCode"); + } + + [Fact] + public async Task Cannot_use_denied_value() + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + ModelStateValidationClient apiClient = new(requestAdapter); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Type = ResourceType.SocialMediaAccounts, + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + Planet = "pluto" + } + } + }; + + // Act + Func action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync()).Which; + response.Errors.Should().HaveCount(1); + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be("The Planet field equals one of the values specified in DeniedValuesAttribute."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/planet"); + } + + [Fact] + public async Task Cannot_use_TimeSpan_outside_of_valid_range() + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + ModelStateValidationClient apiClient = new(requestAdapter); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Type = ResourceType.SocialMediaAccounts, + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + NextRevalidation = TimeSpan.FromSeconds(1).ToString() + } + } + }; + + // Act + Func action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync()).Which; + response.Errors.Should().HaveCount(1); + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be("The field NextRevalidation must be between 01:00:00 and 05:00:00."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/nextRevalidation"); + } + + [Fact] + public async Task Can_create_resource_with_valid_properties() + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + ModelStateValidationClient apiClient = new(requestAdapter); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Type = ResourceType.SocialMediaAccounts, + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + AlternativeId = newAccount.AlternativeId, + FirstName = newAccount.FirstName, + LastName = newAccount.LastName, + UserName = newAccount.UserName, + CreditCard = newAccount.CreditCard, + Email = newAccount.Email, + Password = Convert.FromBase64String(newAccount.Password!), + Phone = newAccount.Phone, + Age = newAccount.Age, + ProfilePicture = newAccount.ProfilePicture!.ToString(), + BackgroundPicture = newAccount.BackgroundPicture, + Tags = newAccount.Tags, + CountryCode = newAccount.CountryCode, + Planet = newAccount.Planet, + NextRevalidation = newAccount.NextRevalidation!.Value.ToString(), + ValidatedAt = newAccount.ValidatedAt!, + ValidatedAtDate = newAccount.ValidatedAtDate!.Value, + ValidatedAtTime = newAccount.ValidatedAtTime!.Value + } + } + }; + + // Act + Func action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody); + + // Assert + await action.Should().NotThrowAsync(); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/UtcDateTimeJsonConverter.cs b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/UtcDateTimeJsonConverter.cs new file mode 100644 index 0000000000..d4d22fa27e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/UtcDateTimeJsonConverter.cs @@ -0,0 +1,18 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace OpenApiKiotaEndToEndTests.ModelStateValidation; + +internal sealed class UtcDateTimeJsonConverter : JsonConverter +{ + public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + DateTimeOffset dateTimeOffset = DateTimeOffset.Parse(reader.GetString()!); + return dateTimeOffset.UtcDateTime; + } + + public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) + { + writer.WriteStringValue(value.ToUniversalTime().ToString("O")); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/OpenApiKiotaEndToEndTests.csproj b/test/OpenApiKiotaEndToEndTests/OpenApiKiotaEndToEndTests.csproj new file mode 100644 index 0000000000..ca0db62217 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/OpenApiKiotaEndToEndTests.csproj @@ -0,0 +1,108 @@ + + + net9.0 + + + + + + + + + + + + + + + + + + + + + + + + AtomicOperations + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + ./%(Name)/GeneratedCode + $(JsonApiExtraArguments) + + + ClientIdGenerationModes + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + ./%(Name)/GeneratedCode + $(JsonApiExtraArguments) + + + Headers + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + ./%(Name)/GeneratedCode + $(JsonApiExtraArguments) + + + Links + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + ./%(Name)/GeneratedCode + $(JsonApiExtraArguments) + + + ModelStateValidation + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + ./%(Name)/GeneratedCode + $(JsonApiExtraArguments) + + + QueryStrings + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + ./%(Name)/GeneratedCode + $(JsonApiExtraArguments) + + + ResourceInheritance + NoOperations + $(MSBuildProjectName).%(Subcategory).%(Name).GeneratedCode + %(Name)InheritanceClient + ./%(Subcategory)/%(Name)/GeneratedCode + $(JsonApiExtraArguments) + + + ResourceInheritance + OnlyRelationships + $(MSBuildProjectName).%(Subcategory).%(Name).GeneratedCode + %(Name)InheritanceClient + ./%(Subcategory)/%(Name)/GeneratedCode + $(JsonApiExtraArguments) + + + ResourceInheritance + SubsetOfOperations + $(MSBuildProjectName).%(Subcategory).%(Name).GeneratedCode + %(Name)InheritanceClient + ./%(Subcategory)/%(Name)/GeneratedCode + $(JsonApiExtraArguments) + + + ResourceInheritance + SubsetOfVarious + $(MSBuildProjectName).%(Subcategory).%(Name).GeneratedCode + %(Name)InheritanceClient + ./%(Subcategory)/%(Name)/GeneratedCode + $(JsonApiExtraArguments) + + + RestrictedControllers + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + ./%(Name)/GeneratedCode + $(JsonApiExtraArguments) + + + diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/FilterTests.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/FilterTests.cs new file mode 100644 index 0000000000..d5de6f1696 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/FilterTests.cs @@ -0,0 +1,183 @@ +using System.Net; +using FluentAssertions; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.QueryStrings; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.QueryStrings; + +public sealed class FilterTests : IClassFixture, QueryStringDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, QueryStringDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly QueryStringFakers _fakers = new(); + + public FilterTests(IntegrationTestContext, QueryStringDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseController(); + } + + [Fact] + public async Task Can_filter_in_primary_resources() + { + // Arrange + List nodes = _fakers.Node.GenerateList(2); + nodes[0].Name = "John No Quote"; + nodes[1].Name = "Brian O'Quote"; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.AddRange(nodes); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new QueryStringsClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["filter"] = "equals(name,'Brian O''Quote')" + }); + + // Act + NodeCollectionResponseDocument? response = await apiClient.Nodes.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(1); + response.Data.ElementAt(0).Id.Should().Be(nodes[1].StringId); + + response.Data.ElementAt(0).Attributes.RefShould().NotBeNull().And.Subject.With(attributes => + { + attributes.Name.Should().Be(nodes[1].Name); + attributes.Comment.Should().Be(nodes[1].Comment); + }); + + response.Meta.Should().NotBeNull(); + response.Meta.AdditionalData.Should().ContainKey("total").WhoseValue.Should().Be(1); + } + + [Fact] + public async Task Can_filter_in_secondary_resources() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Children = _fakers.Node.GenerateSet(2); + node.Children.ElementAt(0).Comment = "Discount: $10"; + node.Children.ElementAt(1).Comment = "Discount: 5%"; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new QueryStringsClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["filter"] = "and(startsWith(comment,'Discount:'),contains(comment,'%'))" + }); + + // Act + NodeCollectionResponseDocument? response = await apiClient.Nodes[node.StringId!].Children.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(1); + response.Data.ElementAt(0).Id.Should().Be(node.Children.ElementAt(1).StringId); + + response.Data.ElementAt(0).Attributes.RefShould().NotBeNull().And.Subject.With(attributes => + { + attributes.Name.Should().Be(node.Children.ElementAt(1).Name); + attributes.Comment.Should().Be(node.Children.ElementAt(1).Comment); + }); + + response.Meta.Should().NotBeNull(); + response.Meta.AdditionalData.Should().ContainKey("total").WhoseValue.Should().Be(1); + } + + [Fact] + public async Task Can_filter_at_ToMany_relationship_endpoint() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Children = _fakers.Node.GenerateSet(2); + node.Children.ElementAt(0).Children = _fakers.Node.GenerateSet(1); + node.Children.ElementAt(1).Children = _fakers.Node.GenerateSet(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new QueryStringsClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["filter"] = "greaterThan(count(children),'1')" + }); + + // Act + NodeIdentifierCollectionResponseDocument? response = await apiClient.Nodes[node.StringId!].Relationships.Children.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(1); + response.Data.ElementAt(0).Id.Should().Be(node.Children.ElementAt(1).StringId); + response.Meta.Should().NotBeNull(); + response.Meta.AdditionalData.Should().ContainKey("total").WhoseValue.Should().Be(1); + response.Links.Should().NotBeNull(); + response.Links.Describedby.Should().Be("/swagger/v1/swagger.json"); + } + + [Fact] + public async Task Cannot_use_empty_filter() + { + // Arrange + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new QueryStringsClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["filter"] = null + }); + + // Act + Func action = async () => _ = await apiClient.Nodes[Unknown.StringId.Int64].GetAsync(); + + // Assert + ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync()).Which; + exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.BadRequest); + exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown."); + exception.Links.Should().NotBeNull(); + exception.Links.Describedby.Should().Be("/swagger/v1/swagger.json"); + exception.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Errors[0]; + error.Status.Should().Be("400"); + error.Title.Should().Be("Missing query string parameter value."); + error.Detail.Should().Be("Missing value for 'filter' query string parameter."); + error.Source.Should().NotBeNull(); + error.Source.Parameter.Should().Be("filter"); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInCreateNameValuePairRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInCreateNameValuePairRequest.cs new file mode 100644 index 0000000000..83e852a185 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInCreateNameValuePairRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateNameValuePairRequest : global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// The value property + public string? Value + { + get { return BackingStore?.Get("value"); } + set { BackingStore?.Set("value", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInCreateNameValuePairRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInCreateNameValuePairRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "name", n => { Name = n.GetStringValue(); } }, + { "value", n => { Value = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("name", Name); + writer.WriteStringValue("value", Value); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInCreateNodeRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInCreateNodeRequest.cs new file mode 100644 index 0000000000..429463d2a5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInCreateNodeRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateNodeRequest : global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The comment property + public string? Comment + { + get { return BackingStore?.Get("comment"); } + set { BackingStore?.Set("comment", value); } + } + + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInCreateNodeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInCreateNodeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "comment", n => { Comment = n.GetStringValue(); } }, + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("comment", Comment); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInCreateRequest.cs new file mode 100644 index 0000000000..31ce729c77 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInCreateRequest.cs @@ -0,0 +1,76 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "nameValuePairs" => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInCreateNameValuePairRequest(), + "nodes" => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInCreateNodeRequest(), + _ => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInNameValuePairResponse.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInNameValuePairResponse.cs new file mode 100644 index 0000000000..5e691ca747 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInNameValuePairResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInNameValuePairResponse : global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// The value property + public string? Value + { + get { return BackingStore?.Get("value"); } + set { BackingStore?.Set("value", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInNameValuePairResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInNameValuePairResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "name", n => { Name = n.GetStringValue(); } }, + { "value", n => { Value = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("name", Name); + writer.WriteStringValue("value", Value); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInNodeResponse.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInNodeResponse.cs new file mode 100644 index 0000000000..cff20802c5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInNodeResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInNodeResponse : global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The comment property + public string? Comment + { + get { return BackingStore?.Get("comment"); } + set { BackingStore?.Set("comment", value); } + } + + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInNodeResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInNodeResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "comment", n => { Comment = n.GetStringValue(); } }, + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("comment", Comment); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInResponse.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInResponse.cs new file mode 100644 index 0000000000..a74152cdd6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInResponse.cs @@ -0,0 +1,76 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "nameValuePairs" => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInNameValuePairResponse(), + "nodes" => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInNodeResponse(), + _ => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInUpdateNameValuePairRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInUpdateNameValuePairRequest.cs new file mode 100644 index 0000000000..3979d32d08 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInUpdateNameValuePairRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateNameValuePairRequest : global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// The value property + public string? Value + { + get { return BackingStore?.Get("value"); } + set { BackingStore?.Set("value", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInUpdateNameValuePairRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInUpdateNameValuePairRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "name", n => { Name = n.GetStringValue(); } }, + { "value", n => { Value = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("name", Name); + writer.WriteStringValue("value", Value); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInUpdateNodeRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInUpdateNodeRequest.cs new file mode 100644 index 0000000000..2dcd9bd224 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInUpdateNodeRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateNodeRequest : global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The comment property + public string? Comment + { + get { return BackingStore?.Get("comment"); } + set { BackingStore?.Set("comment", value); } + } + + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInUpdateNodeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInUpdateNodeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "comment", n => { Comment = n.GetStringValue(); } }, + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("comment", Comment); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInUpdateRequest.cs new file mode 100644 index 0000000000..41597dd5fb --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/AttributesInUpdateRequest.cs @@ -0,0 +1,76 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "nameValuePairs" => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInUpdateNameValuePairRequest(), + "nodes" => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInUpdateNodeRequest(), + _ => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/CreateNameValuePairRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/CreateNameValuePairRequestDocument.cs new file mode 100644 index 0000000000..b72cc6bd95 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/CreateNameValuePairRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateNameValuePairRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInCreateNameValuePairRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateNameValuePairRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.CreateNameValuePairRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.CreateNameValuePairRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInCreateNameValuePairRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/CreateNodeRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/CreateNodeRequestDocument.cs new file mode 100644 index 0000000000..c9489c5c67 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/CreateNodeRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateNodeRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInCreateNodeRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateNodeRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.CreateNodeRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.CreateNodeRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInCreateNodeRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/DataInCreateNameValuePairRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/DataInCreateNameValuePairRequest.cs new file mode 100644 index 0000000000..6214682931 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/DataInCreateNameValuePairRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateNameValuePairRequest : global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInCreateNameValuePairRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInCreateNameValuePairRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInCreateNameValuePairRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInCreateNameValuePairRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInCreateNameValuePairRequest.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInCreateNameValuePairRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/DataInCreateNodeRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/DataInCreateNodeRequest.cs new file mode 100644 index 0000000000..48e6bfc6b6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/DataInCreateNodeRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateNodeRequest : global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInCreateNodeRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInCreateNodeRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInCreateNodeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInCreateNodeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInCreateNodeRequest.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInCreateNodeRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/DataInNameValuePairResponse.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/DataInNameValuePairResponse.cs new file mode 100644 index 0000000000..4d1dd05d94 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/DataInNameValuePairResponse.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInNameValuePairResponse : global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInNameValuePairResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInNameValuePairResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInNameValuePairResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInNameValuePairResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInNameValuePairResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInNameValuePairResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/DataInNodeResponse.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/DataInNodeResponse.cs new file mode 100644 index 0000000000..297d9072eb --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/DataInNodeResponse.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInNodeResponse : global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInNodeResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInNodeResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInNodeResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInNodeResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInNodeResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInNodeResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/DataInUpdateNameValuePairRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/DataInUpdateNameValuePairRequest.cs new file mode 100644 index 0000000000..fb123dff1b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/DataInUpdateNameValuePairRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateNameValuePairRequest : global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInUpdateNameValuePairRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInUpdateNameValuePairRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInUpdateNameValuePairRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInUpdateNameValuePairRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInUpdateNameValuePairRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInUpdateNameValuePairRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/DataInUpdateNodeRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/DataInUpdateNodeRequest.cs new file mode 100644 index 0000000000..b2856cc56c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/DataInUpdateNodeRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateNodeRequest : global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInUpdateNodeRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInUpdateNodeRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInUpdateNodeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInUpdateNodeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.AttributesInUpdateNodeRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInUpdateNodeRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ErrorLinks.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ErrorLinks.cs new file mode 100644 index 0000000000..1b81137154 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ErrorLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// The about property + public string? About + { + get { return BackingStore?.Get("about"); } + set { BackingStore?.Set("about", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The type property + public string? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "about", n => { About = n.GetStringValue(); } }, + { "type", n => { Type = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("about", About); + writer.WriteStringValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ErrorObject.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ErrorObject.cs new file mode 100644 index 0000000000..a77ce1b055 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ErrorObject.cs @@ -0,0 +1,133 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorObject : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The code property + public string? Code + { + get { return BackingStore?.Get("code"); } + set { BackingStore?.Set("code", value); } + } + + /// The detail property + public string? Detail + { + get { return BackingStore?.Get("detail"); } + set { BackingStore?.Set("detail", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The source property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorSource? Source + { + get { return BackingStore?.Get("source"); } + set { BackingStore?.Set("source", value); } + } + + /// The status property + public string? Status + { + get { return BackingStore?.Get("status"); } + set { BackingStore?.Set("status", value); } + } + + /// The title property + public string? Title + { + get { return BackingStore?.Get("title"); } + set { BackingStore?.Set("title", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorObject() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorObject CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorObject(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "code", n => { Code = n.GetStringValue(); } }, + { "detail", n => { Detail = n.GetStringValue(); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "source", n => { Source = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorSource.CreateFromDiscriminatorValue); } }, + { "status", n => { Status = n.GetStringValue(); } }, + { "title", n => { Title = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("code", Code); + writer.WriteStringValue("detail", Detail); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + writer.WriteObjectValue("source", Source); + writer.WriteStringValue("status", Status); + writer.WriteStringValue("title", Title); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ErrorResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ErrorResponseDocument.cs new file mode 100644 index 0000000000..3a149be5b1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ErrorResponseDocument.cs @@ -0,0 +1,92 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorResponseDocument : ApiException, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The errors property + public List? Errors + { + get { return BackingStore?.Get?>("errors"); } + set { BackingStore?.Set("errors", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The primary error message. + public override string Message { get => base.Message; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "errors", n => { Errors = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorObject.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("errors", Errors); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ErrorSource.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ErrorSource.cs new file mode 100644 index 0000000000..e5798125f6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ErrorSource.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorSource : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The header property + public string? Header + { + get { return BackingStore?.Get("header"); } + set { BackingStore?.Set("header", value); } + } + + /// The parameter property + public string? Parameter + { + get { return BackingStore?.Get("parameter"); } + set { BackingStore?.Set("parameter", value); } + } + + /// The pointer property + public string? Pointer + { + get { return BackingStore?.Get("pointer"); } + set { BackingStore?.Set("pointer", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorSource() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorSource CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorSource(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "header", n => { Header = n.GetStringValue(); } }, + { "parameter", n => { Parameter = n.GetStringValue(); } }, + { "pointer", n => { Pointer = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("header", Header); + writer.WriteStringValue("parameter", Parameter); + writer.WriteStringValue("pointer", Pointer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ErrorTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ErrorTopLevelLinks.cs new file mode 100644 index 0000000000..97094d84f2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ErrorTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/IdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/IdentifierInRequest.cs new file mode 100644 index 0000000000..40554d6177 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/IdentifierInRequest.cs @@ -0,0 +1,85 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class IdentifierInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public IdentifierInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.IdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "nameValuePairs" => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NameValuePairIdentifierInRequest(), + "nodes" => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierInRequest(), + _ => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.IdentifierInRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/Meta.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/Meta.cs new file mode 100644 index 0000000000..8f63438119 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/Meta.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class Meta : IAdditionalDataHolder, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + public IDictionary AdditionalData + { + get { return BackingStore.Get>("AdditionalData") ?? new Dictionary(); } + set { BackingStore.Set("AdditionalData", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// + /// Instantiates a new and sets the default values. + /// + public Meta() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + AdditionalData = new Dictionary(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteAdditionalData(AdditionalData); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NameValuePairCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NameValuePairCollectionResponseDocument.cs new file mode 100644 index 0000000000..8f0ed84c22 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NameValuePairCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NameValuePairCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NameValuePairCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NameValuePairCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NameValuePairCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInNameValuePairResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NameValuePairIdentifierCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NameValuePairIdentifierCollectionResponseDocument.cs new file mode 100644 index 0000000000..3191d5c9b9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NameValuePairIdentifierCollectionResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NameValuePairIdentifierCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NameValuePairIdentifierCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NameValuePairIdentifierCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NameValuePairIdentifierCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NameValuePairIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NameValuePairIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NameValuePairIdentifierInRequest.cs new file mode 100644 index 0000000000..f26a216168 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NameValuePairIdentifierInRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NameValuePairIdentifierInRequest : global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NameValuePairIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NameValuePairIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NameValuePairIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NameValuePairIdentifierInResponse.cs new file mode 100644 index 0000000000..b60d4e791c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NameValuePairIdentifierInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NameValuePairIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NameValuePairResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NameValuePairIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NameValuePairIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NameValuePairIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NameValuePairResourceType.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NameValuePairResourceType.cs new file mode 100644 index 0000000000..b38d5fe09d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NameValuePairResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum NameValuePairResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "nameValuePairs")] + #pragma warning disable CS1591 + NameValuePairs, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NodeCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NodeCollectionResponseDocument.cs new file mode 100644 index 0000000000..ed17d2fb0a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NodeCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NodeCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NodeCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInNodeResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NodeIdentifierCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NodeIdentifierCollectionResponseDocument.cs new file mode 100644 index 0000000000..ccc5cc5ac0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NodeIdentifierCollectionResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NodeIdentifierCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NodeIdentifierCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NodeIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NodeIdentifierInRequest.cs new file mode 100644 index 0000000000..bf3423dfc8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NodeIdentifierInRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NodeIdentifierInRequest : global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NodeIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NodeIdentifierInResponse.cs new file mode 100644 index 0000000000..9c02cc83e6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NodeIdentifierInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NodeIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NodeIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NodeIdentifierResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NodeIdentifierResponseDocument.cs new file mode 100644 index 0000000000..36b8fd7a09 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NodeIdentifierResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NodeIdentifierResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceIdentifierTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NodeIdentifierResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceIdentifierTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NodeResourceType.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NodeResourceType.cs new file mode 100644 index 0000000000..42c31c0a7c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NodeResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum NodeResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "nodes")] + #pragma warning disable CS1591 + Nodes, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NullableNodeIdentifierResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NullableNodeIdentifierResponseDocument.cs new file mode 100644 index 0000000000..32b0161cfe --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NullableNodeIdentifierResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NullableNodeIdentifierResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceIdentifierTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NullableNodeIdentifierResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NullableNodeIdentifierResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NullableNodeIdentifierResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceIdentifierTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NullableSecondaryNodeResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NullableSecondaryNodeResponseDocument.cs new file mode 100644 index 0000000000..d29a252b19 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NullableSecondaryNodeResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NullableSecondaryNodeResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInNodeResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NullableSecondaryNodeResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NullableSecondaryNodeResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NullableSecondaryNodeResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInNodeResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NullableToOneNodeInRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NullableToOneNodeInRequest.cs new file mode 100644 index 0000000000..876627be18 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NullableToOneNodeInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NullableToOneNodeInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierInRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NullableToOneNodeInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NullableToOneNodeInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NullableToOneNodeInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierInRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NullableToOneNodeInResponse.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NullableToOneNodeInResponse.cs new file mode 100644 index 0000000000..26282c294b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/NullableToOneNodeInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NullableToOneNodeInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NullableToOneNodeInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NullableToOneNodeInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NullableToOneNodeInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/PrimaryNameValuePairResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/PrimaryNameValuePairResponseDocument.cs new file mode 100644 index 0000000000..e2e0a23b1c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/PrimaryNameValuePairResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryNameValuePairResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInNameValuePairResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryNameValuePairResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.PrimaryNameValuePairResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.PrimaryNameValuePairResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInNameValuePairResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/PrimaryNodeResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/PrimaryNodeResponseDocument.cs new file mode 100644 index 0000000000..2bcbbde79d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/PrimaryNodeResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryNodeResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInNodeResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryNodeResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.PrimaryNodeResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.PrimaryNodeResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInNodeResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipLinks.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipLinks.cs new file mode 100644 index 0000000000..04cb85e4f0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInCreateNameValuePairRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInCreateNameValuePairRequest.cs new file mode 100644 index 0000000000..e2fca0c85a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInCreateNameValuePairRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateNameValuePairRequest : global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The owner property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToOneNodeInRequest? Owner + { + get { return BackingStore?.Get("owner"); } + set { BackingStore?.Set("owner", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInCreateNameValuePairRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInCreateNameValuePairRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "owner", n => { Owner = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToOneNodeInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("owner", Owner); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInCreateNodeRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInCreateNodeRequest.cs new file mode 100644 index 0000000000..440c5a1a67 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInCreateNodeRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateNodeRequest : global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The children property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNodeInRequest? Children + { + get { return BackingStore?.Get("children"); } + set { BackingStore?.Set("children", value); } + } + + /// The parent property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NullableToOneNodeInRequest? Parent + { + get { return BackingStore?.Get("parent"); } + set { BackingStore?.Set("parent", value); } + } + + /// The values property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNameValuePairInRequest? Values + { + get { return BackingStore?.Get("values"); } + set { BackingStore?.Set("values", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInCreateNodeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInCreateNodeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "children", n => { Children = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNodeInRequest.CreateFromDiscriminatorValue); } }, + { "parent", n => { Parent = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NullableToOneNodeInRequest.CreateFromDiscriminatorValue); } }, + { "values", n => { Values = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNameValuePairInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("children", Children); + writer.WriteObjectValue("parent", Parent); + writer.WriteObjectValue("values", Values); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInCreateRequest.cs new file mode 100644 index 0000000000..9abf8566da --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInCreateRequest.cs @@ -0,0 +1,76 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "nameValuePairs" => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInCreateNameValuePairRequest(), + "nodes" => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInCreateNodeRequest(), + _ => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInNameValuePairResponse.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInNameValuePairResponse.cs new file mode 100644 index 0000000000..fc77dd9aa1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInNameValuePairResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInNameValuePairResponse : global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// The owner property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToOneNodeInResponse? Owner + { + get { return BackingStore?.Get("owner"); } + set { BackingStore?.Set("owner", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInNameValuePairResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInNameValuePairResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "owner", n => { Owner = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToOneNodeInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("owner", Owner); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInNodeResponse.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInNodeResponse.cs new file mode 100644 index 0000000000..685406b888 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInNodeResponse.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInNodeResponse : global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// The children property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNodeInResponse? Children + { + get { return BackingStore?.Get("children"); } + set { BackingStore?.Set("children", value); } + } + + /// The parent property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NullableToOneNodeInResponse? Parent + { + get { return BackingStore?.Get("parent"); } + set { BackingStore?.Set("parent", value); } + } + + /// The values property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNameValuePairInResponse? Values + { + get { return BackingStore?.Get("values"); } + set { BackingStore?.Set("values", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInNodeResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInNodeResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "children", n => { Children = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNodeInResponse.CreateFromDiscriminatorValue); } }, + { "parent", n => { Parent = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NullableToOneNodeInResponse.CreateFromDiscriminatorValue); } }, + { "values", n => { Values = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNameValuePairInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("children", Children); + writer.WriteObjectValue("parent", Parent); + writer.WriteObjectValue("values", Values); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInResponse.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInResponse.cs new file mode 100644 index 0000000000..65b7ac3e6a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInResponse.cs @@ -0,0 +1,76 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "nameValuePairs" => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInNameValuePairResponse(), + "nodes" => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInNodeResponse(), + _ => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInUpdateNameValuePairRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInUpdateNameValuePairRequest.cs new file mode 100644 index 0000000000..488ff75aee --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInUpdateNameValuePairRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateNameValuePairRequest : global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The owner property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToOneNodeInRequest? Owner + { + get { return BackingStore?.Get("owner"); } + set { BackingStore?.Set("owner", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInUpdateNameValuePairRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInUpdateNameValuePairRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "owner", n => { Owner = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToOneNodeInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("owner", Owner); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInUpdateNodeRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInUpdateNodeRequest.cs new file mode 100644 index 0000000000..bc58cc23b7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInUpdateNodeRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateNodeRequest : global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The children property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNodeInRequest? Children + { + get { return BackingStore?.Get("children"); } + set { BackingStore?.Set("children", value); } + } + + /// The parent property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NullableToOneNodeInRequest? Parent + { + get { return BackingStore?.Get("parent"); } + set { BackingStore?.Set("parent", value); } + } + + /// The values property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNameValuePairInRequest? Values + { + get { return BackingStore?.Get("values"); } + set { BackingStore?.Set("values", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInUpdateNodeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInUpdateNodeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "children", n => { Children = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNodeInRequest.CreateFromDiscriminatorValue); } }, + { "parent", n => { Parent = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NullableToOneNodeInRequest.CreateFromDiscriminatorValue); } }, + { "values", n => { Values = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNameValuePairInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("children", Children); + writer.WriteObjectValue("parent", Parent); + writer.WriteObjectValue("values", Values); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInUpdateRequest.cs new file mode 100644 index 0000000000..b3aafacc11 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/RelationshipsInUpdateRequest.cs @@ -0,0 +1,76 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "nameValuePairs" => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInUpdateNameValuePairRequest(), + "nodes" => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInUpdateNodeRequest(), + _ => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipsInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceCollectionTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceCollectionTopLevelLinks.cs new file mode 100644 index 0000000000..0c8f5216aa --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceCollectionTopLevelLinks.cs @@ -0,0 +1,115 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceCollectionTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The first property + public string? First + { + get { return BackingStore?.Get("first"); } + set { BackingStore?.Set("first", value); } + } + + /// The last property + public string? Last + { + get { return BackingStore?.Get("last"); } + set { BackingStore?.Set("last", value); } + } + + /// The next property + public string? Next + { + get { return BackingStore?.Get("next"); } + set { BackingStore?.Set("next", value); } + } + + /// The prev property + public string? Prev + { + get { return BackingStore?.Get("prev"); } + set { BackingStore?.Set("prev", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceCollectionTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceCollectionTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceCollectionTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "first", n => { First = n.GetStringValue(); } }, + { "last", n => { Last = n.GetStringValue(); } }, + { "next", n => { Next = n.GetStringValue(); } }, + { "prev", n => { Prev = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("first", First); + writer.WriteStringValue("last", Last); + writer.WriteStringValue("next", Next); + writer.WriteStringValue("prev", Prev); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs new file mode 100644 index 0000000000..c9627a36f3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs @@ -0,0 +1,124 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceIdentifierCollectionTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The first property + public string? First + { + get { return BackingStore?.Get("first"); } + set { BackingStore?.Set("first", value); } + } + + /// The last property + public string? Last + { + get { return BackingStore?.Get("last"); } + set { BackingStore?.Set("last", value); } + } + + /// The next property + public string? Next + { + get { return BackingStore?.Get("next"); } + set { BackingStore?.Set("next", value); } + } + + /// The prev property + public string? Prev + { + get { return BackingStore?.Get("prev"); } + set { BackingStore?.Set("prev", value); } + } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceIdentifierCollectionTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "first", n => { First = n.GetStringValue(); } }, + { "last", n => { Last = n.GetStringValue(); } }, + { "next", n => { Next = n.GetStringValue(); } }, + { "prev", n => { Prev = n.GetStringValue(); } }, + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("first", First); + writer.WriteStringValue("last", Last); + writer.WriteStringValue("next", Next); + writer.WriteStringValue("prev", Prev); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceIdentifierTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceIdentifierTopLevelLinks.cs new file mode 100644 index 0000000000..03fb12891e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceIdentifierTopLevelLinks.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceIdentifierTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceIdentifierTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceIdentifierTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceIdentifierTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceInCreateRequest.cs new file mode 100644 index 0000000000..6d451530ab --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceInCreateRequest.cs @@ -0,0 +1,85 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "nameValuePairs" => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInCreateNameValuePairRequest(), + "nodes" => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInCreateNodeRequest(), + _ => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceInResponse.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceInResponse.cs new file mode 100644 index 0000000000..ac2165ae82 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceInResponse.cs @@ -0,0 +1,85 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "nameValuePairs" => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInNameValuePairResponse(), + "nodes" => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInNodeResponse(), + _ => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceInUpdateRequest.cs new file mode 100644 index 0000000000..40a5b9dcc0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceInUpdateRequest.cs @@ -0,0 +1,85 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "nameValuePairs" => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInUpdateNameValuePairRequest(), + "nodes" => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInUpdateNodeRequest(), + _ => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceLinks.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceLinks.cs new file mode 100644 index 0000000000..c3ae0a3daa --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceLinks.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceTopLevelLinks.cs new file mode 100644 index 0000000000..9e454942fe --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceType.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceType.cs new file mode 100644 index 0000000000..b1d2f918b0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ResourceType.cs @@ -0,0 +1,22 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum ResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "nameValuePairs")] + #pragma warning disable CS1591 + NameValuePairs, + #pragma warning restore CS1591 + [EnumMember(Value = "nodes")] + #pragma warning disable CS1591 + Nodes, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/SecondaryNodeResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/SecondaryNodeResponseDocument.cs new file mode 100644 index 0000000000..684c5459c3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/SecondaryNodeResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class SecondaryNodeResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInNodeResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public SecondaryNodeResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.SecondaryNodeResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.SecondaryNodeResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInNodeResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ToManyNameValuePairInRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ToManyNameValuePairInRequest.cs new file mode 100644 index 0000000000..ae84aa2be2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ToManyNameValuePairInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyNameValuePairInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyNameValuePairInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNameValuePairInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNameValuePairInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NameValuePairIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ToManyNameValuePairInResponse.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ToManyNameValuePairInResponse.cs new file mode 100644 index 0000000000..661bf211ac --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ToManyNameValuePairInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyNameValuePairInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyNameValuePairInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNameValuePairInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNameValuePairInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NameValuePairIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ToManyNodeInRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ToManyNodeInRequest.cs new file mode 100644 index 0000000000..d3c3da6b00 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ToManyNodeInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyNodeInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyNodeInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNodeInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNodeInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ToManyNodeInResponse.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ToManyNodeInResponse.cs new file mode 100644 index 0000000000..81c8be374e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ToManyNodeInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyNodeInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyNodeInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNodeInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNodeInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ToOneNodeInRequest.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ToOneNodeInRequest.cs new file mode 100644 index 0000000000..caaf390dc2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ToOneNodeInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToOneNodeInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierInRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToOneNodeInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToOneNodeInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToOneNodeInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierInRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ToOneNodeInResponse.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ToOneNodeInResponse.cs new file mode 100644 index 0000000000..4c22e1a2be --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/ToOneNodeInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToOneNodeInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToOneNodeInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToOneNodeInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToOneNodeInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/UpdateNameValuePairRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/UpdateNameValuePairRequestDocument.cs new file mode 100644 index 0000000000..b5533b51f4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/UpdateNameValuePairRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateNameValuePairRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInUpdateNameValuePairRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateNameValuePairRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.UpdateNameValuePairRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.UpdateNameValuePairRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInUpdateNameValuePairRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/UpdateNodeRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/UpdateNodeRequestDocument.cs new file mode 100644 index 0000000000..090d6f4a8c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Models/UpdateNodeRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateNodeRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInUpdateNodeRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateNodeRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.UpdateNodeRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.UpdateNodeRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.DataInUpdateNodeRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/NameValuePairs/Item/NameValuePairsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/NameValuePairs/Item/NameValuePairsItemRequestBuilder.cs new file mode 100644 index 0000000000..01e6a4b666 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/NameValuePairs/Item/NameValuePairsItemRequestBuilder.cs @@ -0,0 +1,223 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.Item.Owner; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.Item.Relationships; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.Item +{ + /// + /// Builds and executes requests for operations under \nameValuePairs\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class NameValuePairsItemRequestBuilder : BaseRequestBuilder + { + /// The owner property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.Item.Owner.OwnerRequestBuilder Owner + { + get => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.Item.Owner.OwnerRequestBuilder(PathParameters, RequestAdapter); + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public NameValuePairsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nameValuePairs/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public NameValuePairsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nameValuePairs/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing nameValuePair by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual nameValuePair by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.PrimaryNameValuePairResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing nameValuePair. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.UpdateNameValuePairRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.PrimaryNameValuePairResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing nameValuePair by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual nameValuePair by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing nameValuePair. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.UpdateNameValuePairRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.Item.NameValuePairsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.Item.NameValuePairsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual nameValuePair by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class NameValuePairsItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class NameValuePairsItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing nameValuePair. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class NameValuePairsItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/NameValuePairs/Item/Owner/OwnerRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/NameValuePairs/Item/Owner/OwnerRequestBuilder.cs new file mode 100644 index 0000000000..0c1b7a4ad9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/NameValuePairs/Item/Owner/OwnerRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.Item.Owner +{ + /// + /// Builds and executes requests for operations under \nameValuePairs\{id}\owner + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OwnerRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public OwnerRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nameValuePairs/{id}/owner{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public OwnerRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nameValuePairs/{id}/owner{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related node of an individual nameValuePair's owner relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.SecondaryNodeResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related node of an individual nameValuePair's owner relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.Item.Owner.OwnerRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.Item.Owner.OwnerRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related node of an individual nameValuePair's owner relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OwnerRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OwnerRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/NameValuePairs/Item/Relationships/Owner/OwnerRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/NameValuePairs/Item/Relationships/Owner/OwnerRequestBuilder.cs new file mode 100644 index 0000000000..f0df923e59 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/NameValuePairs/Item/Relationships/Owner/OwnerRequestBuilder.cs @@ -0,0 +1,168 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.Item.Relationships.Owner +{ + /// + /// Builds and executes requests for operations under \nameValuePairs\{id}\relationships\owner + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OwnerRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public OwnerRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nameValuePairs/{id}/relationships/owner{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public OwnerRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nameValuePairs/{id}/relationships/owner{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related node identity of an individual nameValuePair's owner relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns an existing node to the owner relationship of an individual nameValuePair. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToOneNodeInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related node identity of an individual nameValuePair's owner relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns an existing node to the owner relationship of an individual nameValuePair. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToOneNodeInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.Item.Relationships.Owner.OwnerRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.Item.Relationships.Owner.OwnerRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related node identity of an individual nameValuePair's owner relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OwnerRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OwnerRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/NameValuePairs/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/NameValuePairs/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..b93bb6eb8d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/NameValuePairs/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.Item.Relationships.Owner; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \nameValuePairs\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The owner property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.Item.Relationships.Owner.OwnerRequestBuilder Owner + { + get => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.Item.Relationships.Owner.OwnerRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nameValuePairs/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nameValuePairs/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/NameValuePairs/NameValuePairsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/NameValuePairs/NameValuePairsRequestBuilder.cs new file mode 100644 index 0000000000..4aa6e73ee1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/NameValuePairs/NameValuePairsRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs +{ + /// + /// Builds and executes requests for operations under \nameValuePairs + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class NameValuePairsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.nameValuePairs.item collection + /// The identifier of the nameValuePair to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.Item.NameValuePairsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.Item.NameValuePairsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public NameValuePairsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nameValuePairs{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public NameValuePairsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nameValuePairs{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of nameValuePairs. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NameValuePairCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new nameValuePair. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.CreateNameValuePairRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.PrimaryNameValuePairResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of nameValuePairs. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new nameValuePair. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.CreateNameValuePairRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.NameValuePairsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.NameValuePairsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of nameValuePairs. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class NameValuePairsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class NameValuePairsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new nameValuePair. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class NameValuePairsRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/Children/ChildrenRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/Children/ChildrenRequestBuilder.cs new file mode 100644 index 0000000000..530deaaa1c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/Children/ChildrenRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Children +{ + /// + /// Builds and executes requests for operations under \nodes\{id}\children + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ChildrenRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ChildrenRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nodes/{id}/children{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ChildrenRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nodes/{id}/children{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related nodes of an individual node's children relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related nodes of an individual node's children relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Children.ChildrenRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Children.ChildrenRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related nodes of an individual node's children relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ChildrenRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ChildrenRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/NodesItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/NodesItemRequestBuilder.cs new file mode 100644 index 0000000000..6c0219db29 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/NodesItemRequestBuilder.cs @@ -0,0 +1,237 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Children; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Parent; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Relationships; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Values; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item +{ + /// + /// Builds and executes requests for operations under \nodes\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class NodesItemRequestBuilder : BaseRequestBuilder + { + /// The children property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Children.ChildrenRequestBuilder Children + { + get => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Children.ChildrenRequestBuilder(PathParameters, RequestAdapter); + } + + /// The parent property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Parent.ParentRequestBuilder Parent + { + get => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Parent.ParentRequestBuilder(PathParameters, RequestAdapter); + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The values property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Values.ValuesRequestBuilder Values + { + get => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Values.ValuesRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public NodesItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nodes/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public NodesItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nodes/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing node by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual node by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.PrimaryNodeResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing node. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.UpdateNodeRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.PrimaryNodeResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing node by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual node by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing node. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.UpdateNodeRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.NodesItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.NodesItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual node by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class NodesItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class NodesItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing node. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class NodesItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/Parent/ParentRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/Parent/ParentRequestBuilder.cs new file mode 100644 index 0000000000..92f0ca7e02 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/Parent/ParentRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Parent +{ + /// + /// Builds and executes requests for operations under \nodes\{id}\parent + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ParentRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ParentRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nodes/{id}/parent{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ParentRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nodes/{id}/parent{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related node of an individual node's parent relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NullableSecondaryNodeResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related node of an individual node's parent relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Parent.ParentRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Parent.ParentRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related node of an individual node's parent relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ParentRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ParentRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/Relationships/Children/ChildrenRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/Relationships/Children/ChildrenRequestBuilder.cs new file mode 100644 index 0000000000..ccc60c94e2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/Relationships/Children/ChildrenRequestBuilder.cs @@ -0,0 +1,248 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Relationships.Children +{ + /// + /// Builds and executes requests for operations under \nodes\{id}\relationships\children + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ChildrenRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ChildrenRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nodes/{id}/relationships/children{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ChildrenRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nodes/{id}/relationships/children{?query*}", rawUrl) + { + } + + /// + /// Removes existing nodes from the children relationship of an individual node. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task DeleteAsync(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNodeInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToDeleteRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related node identities of an individual node's children relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeIdentifierCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns existing nodes to the children relationship of an individual node. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNodeInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Adds existing nodes to the children relationship of an individual node. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNodeInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Removes existing nodes from the children relationship of an individual node. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNodeInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Retrieves the related node identities of an individual node's children relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns existing nodes to the children relationship of an individual node. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNodeInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Adds existing nodes to the children relationship of an individual node. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNodeInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Relationships.Children.ChildrenRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Relationships.Children.ChildrenRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related node identities of an individual node's children relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ChildrenRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ChildrenRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/Relationships/Parent/ParentRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/Relationships/Parent/ParentRequestBuilder.cs new file mode 100644 index 0000000000..615942d349 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/Relationships/Parent/ParentRequestBuilder.cs @@ -0,0 +1,168 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Relationships.Parent +{ + /// + /// Builds and executes requests for operations under \nodes\{id}\relationships\parent + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ParentRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ParentRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nodes/{id}/relationships/parent{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ParentRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nodes/{id}/relationships/parent{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related node identity of an individual node's parent relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NullableNodeIdentifierResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Clears or assigns an existing node to the parent relationship of an individual node. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NullableToOneNodeInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related node identity of an individual node's parent relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Clears or assigns an existing node to the parent relationship of an individual node. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NullableToOneNodeInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Relationships.Parent.ParentRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Relationships.Parent.ParentRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related node identity of an individual node's parent relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ParentRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ParentRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..c7c1b3238a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Relationships.Children; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Relationships.Parent; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Relationships.Values; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \nodes\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The children property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Relationships.Children.ChildrenRequestBuilder Children + { + get => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Relationships.Children.ChildrenRequestBuilder(PathParameters, RequestAdapter); + } + + /// The parent property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Relationships.Parent.ParentRequestBuilder Parent + { + get => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Relationships.Parent.ParentRequestBuilder(PathParameters, RequestAdapter); + } + + /// The values property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Relationships.Values.ValuesRequestBuilder Values + { + get => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Relationships.Values.ValuesRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nodes/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nodes/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/Relationships/Values/ValuesRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/Relationships/Values/ValuesRequestBuilder.cs new file mode 100644 index 0000000000..8f7da24dc4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/Relationships/Values/ValuesRequestBuilder.cs @@ -0,0 +1,248 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Relationships.Values +{ + /// + /// Builds and executes requests for operations under \nodes\{id}\relationships\values + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ValuesRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ValuesRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nodes/{id}/relationships/values{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ValuesRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nodes/{id}/relationships/values{?query*}", rawUrl) + { + } + + /// + /// Removes existing nameValuePairs from the values relationship of an individual node. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task DeleteAsync(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNameValuePairInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToDeleteRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related nameValuePair identities of an individual node's values relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NameValuePairIdentifierCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns existing nameValuePairs to the values relationship of an individual node. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNameValuePairInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Adds existing nameValuePairs to the values relationship of an individual node. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNameValuePairInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Removes existing nameValuePairs from the values relationship of an individual node. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNameValuePairInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Retrieves the related nameValuePair identities of an individual node's values relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns existing nameValuePairs to the values relationship of an individual node. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNameValuePairInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Adds existing nameValuePairs to the values relationship of an individual node. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ToManyNameValuePairInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Relationships.Values.ValuesRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Relationships.Values.ValuesRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related nameValuePair identities of an individual node's values relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ValuesRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ValuesRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/Values/ValuesRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/Values/ValuesRequestBuilder.cs new file mode 100644 index 0000000000..93d0afad2d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/Item/Values/ValuesRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Values +{ + /// + /// Builds and executes requests for operations under \nodes\{id}\values + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ValuesRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ValuesRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nodes/{id}/values{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ValuesRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nodes/{id}/values{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related nameValuePairs of an individual node's values relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NameValuePairCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related nameValuePairs of an individual node's values relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Values.ValuesRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.Values.ValuesRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related nameValuePairs of an individual node's values relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ValuesRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ValuesRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/NodesRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/NodesRequestBuilder.cs new file mode 100644 index 0000000000..e5f1ddec6c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/Nodes/NodesRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes +{ + /// + /// Builds and executes requests for operations under \nodes + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class NodesRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.nodes.item collection + /// The identifier of the node to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.NodesItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.Item.NodesItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public NodesRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nodes{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public NodesRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/nodes{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of nodes. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.NodeCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new node. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.CreateNodeRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.PrimaryNodeResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of nodes. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new node. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models.CreateNodeRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.NodesRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.NodesRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of nodes. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class NodesRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class NodesRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new node. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class NodesRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/QueryStringsClient.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/QueryStringsClient.cs new file mode 100644 index 0000000000..509ff5803b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/QueryStringsClient.cs @@ -0,0 +1,61 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using Microsoft.Kiota.Serialization.Form; +using Microsoft.Kiota.Serialization.Json; +using Microsoft.Kiota.Serialization.Multipart; +using Microsoft.Kiota.Serialization.Text; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode +{ + /// + /// The main entry point of the SDK, exposes the configuration and the fluent API. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class QueryStringsClient : BaseRequestBuilder + { + /// The nameValuePairs property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.NameValuePairsRequestBuilder NameValuePairs + { + get => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.NameValuePairs.NameValuePairsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The nodes property + public global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.NodesRequestBuilder Nodes + { + get => new global::OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Nodes.NodesRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The backing store to use for the models. + /// The request adapter to use to execute the requests. + public QueryStringsClient(IRequestAdapter requestAdapter, IBackingStoreFactory backingStore = default) : base(requestAdapter, "{+baseurl}", new Dictionary()) + { + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + if (string.IsNullOrEmpty(RequestAdapter.BaseUrl)) + { + RequestAdapter.BaseUrl = "http://localhost"; + } + PathParameters.TryAdd("baseurl", RequestAdapter.BaseUrl); + RequestAdapter.EnableBackingStore(backingStore); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/IncludeTests.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/IncludeTests.cs new file mode 100644 index 0000000000..0b1276b5ec --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/IncludeTests.cs @@ -0,0 +1,210 @@ +using FluentAssertions; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.QueryStrings; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.QueryStrings; + +public sealed class IncludeTests : IClassFixture, QueryStringDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, QueryStringDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly QueryStringFakers _fakers = new(); + + public IncludeTests(IntegrationTestContext, QueryStringDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseController(); + testContext.UseController(); + } + + [Fact] + public async Task Can_include_in_primary_resources() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Values = _fakers.NameValuePair.GenerateList(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new QueryStringsClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["include"] = "values.owner" + }); + + // Act + NodeCollectionResponseDocument? response = await apiClient.Nodes.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(1); + response.Data.ElementAt(0).Id.Should().Be(node.StringId); + + response.Included.Should().HaveCount(2); + response.Included.OfType().Should().ContainSingle(include => include.Id == node.Values.ElementAt(0).StringId); + response.Included.OfType().Should().ContainSingle(include => include.Id == node.Values.ElementAt(1).StringId); + } + + [Fact] + public async Task Can_include_in_primary_resource() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Values = _fakers.NameValuePair.GenerateList(1); + node.Children = _fakers.Node.GenerateSet(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new QueryStringsClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["include"] = "children.parent,values" + }); + + // Act + PrimaryNodeResponseDocument? response = await apiClient.Nodes[node.StringId!].GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().NotBeNull(); + response.Data.Id.Should().Be(node.StringId); + + response.Included.Should().HaveCount(3); + response.Included.OfType().Should().ContainSingle(include => include.Id == node.Children.ElementAt(0).StringId); + response.Included.OfType().Should().ContainSingle(include => include.Id == node.Children.ElementAt(1).StringId); + response.Included.OfType().Should().ContainSingle(include => include.Id == node.Values[0].StringId); + } + + [Fact] + public async Task Can_include_in_secondary_resources() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Parent = _fakers.Node.GenerateOne(); + node.Values = _fakers.NameValuePair.GenerateList(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new QueryStringsClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["include"] = "owner.parent,owner.values" + }); + + // Act + NameValuePairCollectionResponseDocument? response = await apiClient.Nodes[node.StringId!].Values.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(2); + + response.Included.Should().HaveCount(2); + response.Included.OfType().Should().ContainSingle(include => include.Id == node.StringId); + response.Included.OfType().Should().ContainSingle(include => include.Id == node.Parent.StringId); + } + + [Fact] + public async Task Can_include_in_secondary_resource() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Parent = _fakers.Node.GenerateOne(); + node.Parent.Parent = _fakers.Node.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new QueryStringsClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["include"] = "parent.parent" + }); + + // Act + NullableSecondaryNodeResponseDocument? response = await apiClient.Nodes[node.StringId!].Parent.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().NotBeNull(); + response.Data.Id.Should().Be(node.Parent.StringId); + + response.Included.Should().HaveCount(1); + + response.Included.OfType().Should().ContainSingle(include => include.Id == node.Parent.Parent.StringId).Subject.With(include => + { + include.Attributes.Should().NotBeNull(); + include.Attributes.Name.Should().Be(node.Parent.Parent.Name); + }); + } + + [Fact] + public async Task Can_use_empty_include() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new QueryStringsClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["include"] = null + }); + + // Act + PrimaryNodeResponseDocument? response = await apiClient.Nodes[node.StringId!].GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().NotBeNull(); + response.Data.Id.Should().Be(node.StringId); + + response.Included.Should().BeEmpty(); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/PaginationTests.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/PaginationTests.cs new file mode 100644 index 0000000000..8fcd76a0c8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/PaginationTests.cs @@ -0,0 +1,192 @@ +using System.Net; +using FluentAssertions; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.QueryStrings; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.QueryStrings; + +public sealed class PaginationTests : IClassFixture, QueryStringDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, QueryStringDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly QueryStringFakers _fakers = new(); + + public PaginationTests(IntegrationTestContext, QueryStringDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseController(); + } + + [Fact] + public async Task Can_paginate_in_primary_resources() + { + // Arrange + List nodes = _fakers.Node.GenerateList(3); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.AddRange(nodes); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new QueryStringsClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["page[size]"] = "1", + ["page[number]"] = "2" + }); + + // Act + NodeCollectionResponseDocument? response = await apiClient.Nodes.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(1); + response.Data.ElementAt(0).Id.Should().Be(nodes[1].StringId); + response.Meta.Should().NotBeNull(); + response.Meta.AdditionalData.Should().ContainKey("total").WhoseValue.Should().Be(3); + } + + [Fact] + public async Task Can_paginate_in_secondary_resources() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Children = _fakers.Node.GenerateSet(3); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new QueryStringsClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["page[size]"] = "2", + ["page[number]"] = "1" + }); + + // Act + NodeCollectionResponseDocument? response = await apiClient.Nodes[node.StringId!].Children.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(2); + response.Data.ElementAt(0).Id.Should().Be(node.Children.ElementAt(0).StringId); + response.Data.ElementAt(1).Id.Should().Be(node.Children.ElementAt(1).StringId); + response.Meta.Should().NotBeNull(); + response.Meta.AdditionalData.Should().ContainKey("total").WhoseValue.Should().Be(3); + } + + [Fact] + public async Task Can_paginate_at_ToMany_relationship_endpoint() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Children = _fakers.Node.GenerateSet(3); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new QueryStringsClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["page[size]"] = "2", + ["page[number]"] = "2" + }); + + // Act + NodeIdentifierCollectionResponseDocument? response = await apiClient.Nodes[node.StringId!].Relationships.Children.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(1); + response.Data.ElementAt(0).Id.Should().Be(node.Children.ElementAt(2).StringId); + response.Meta.Should().NotBeNull(); + response.Meta.AdditionalData.Should().ContainKey("total").WhoseValue.Should().Be(3); + } + + [Fact] + public async Task Cannot_use_empty_page_size() + { + // Arrange + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new QueryStringsClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["page[size]"] = null + }); + + // Act + Func action = async () => _ = await apiClient.Nodes[Unknown.StringId.Int64].GetAsync(); + + // Assert + ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync()).Which; + exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.BadRequest); + exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown."); + exception.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Errors.ElementAt(0); + error.Status.Should().Be("400"); + error.Title.Should().Be("Missing query string parameter value."); + error.Detail.Should().Be("Missing value for 'page[size]' query string parameter."); + error.Source.Should().NotBeNull(); + error.Source.Parameter.Should().Be("page[size]"); + } + + [Fact] + public async Task Cannot_use_empty_page_number() + { + // Arrange + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new QueryStringsClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["page[number]"] = null + }); + + // Act + Func action = async () => _ = await apiClient.Nodes[Unknown.StringId.Int64].GetAsync(); + + // Assert + ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync()).Which; + exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.BadRequest); + exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown."); + exception.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Errors.ElementAt(0); + error.Status.Should().Be("400"); + error.Title.Should().Be("Missing query string parameter value."); + error.Detail.Should().Be("Missing value for 'page[number]' query string parameter."); + error.Source.Should().NotBeNull(); + error.Source.Parameter.Should().Be("page[number]"); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/SortTests.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/SortTests.cs new file mode 100644 index 0000000000..477164531a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/SortTests.cs @@ -0,0 +1,162 @@ +using System.Net; +using FluentAssertions; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.QueryStrings; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.QueryStrings; + +public sealed class SortTests : IClassFixture, QueryStringDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, QueryStringDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly QueryStringFakers _fakers = new(); + + public SortTests(IntegrationTestContext, QueryStringDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseController(); + } + + [Fact] + public async Task Can_sort_in_primary_resources() + { + // Arrange + List nodes = _fakers.Node.GenerateList(2); + nodes[0].Name = "A"; + nodes[1].Name = "B"; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.AddRange(nodes); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new QueryStringsClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["sort"] = "-name" + }); + + // Act + NodeCollectionResponseDocument? response = await apiClient.Nodes.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(2); + response.Data.ElementAt(0).Id.Should().Be(nodes[1].StringId); + response.Data.ElementAt(1).Id.Should().Be(nodes[0].StringId); + } + + [Fact] + public async Task Can_sort_in_secondary_resources() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Children = _fakers.Node.GenerateSet(2); + node.Children.ElementAt(0).Name = "B"; + node.Children.ElementAt(1).Name = "A"; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new QueryStringsClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["sort"] = "name" + }); + + // Act + NodeCollectionResponseDocument? response = await apiClient.Nodes[node.StringId!].Children.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(2); + response.Data.ElementAt(0).Id.Should().Be(node.Children.ElementAt(1).StringId); + response.Data.ElementAt(1).Id.Should().Be(node.Children.ElementAt(0).StringId); + } + + [Fact] + public async Task Can_sort_at_ToMany_relationship_endpoint() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Children = _fakers.Node.GenerateSet(2); + node.Children.ElementAt(0).Children = _fakers.Node.GenerateSet(1); + node.Children.ElementAt(1).Children = _fakers.Node.GenerateSet(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new QueryStringsClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["sort"] = "count(children)" + }); + + // Act + NodeIdentifierCollectionResponseDocument? response = await apiClient.Nodes[node.StringId!].Relationships.Children.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(2); + response.Data.ElementAt(0).Id.Should().Be(node.Children.ElementAt(0).StringId); + response.Data.ElementAt(1).Id.Should().Be(node.Children.ElementAt(1).StringId); + } + + [Fact] + public async Task Cannot_use_empty_sort() + { + // Arrange + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new QueryStringsClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["sort"] = null + }); + + // Act + Func action = async () => _ = await apiClient.Nodes[Unknown.StringId.Int64].GetAsync(); + + // Assert + ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync()).Which; + exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.BadRequest); + exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown."); + exception.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Errors.ElementAt(0); + error.Status.Should().Be("400"); + error.Title.Should().Be("Missing query string parameter value."); + error.Detail.Should().Be("Missing value for 'sort' query string parameter."); + error.Source.Should().NotBeNull(); + error.Source.Parameter.Should().Be("sort"); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/SparseFieldSetTests.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/SparseFieldSetTests.cs new file mode 100644 index 0000000000..f2d76023f8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/SparseFieldSetTests.cs @@ -0,0 +1,214 @@ +using FluentAssertions; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode; +using OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.QueryStrings; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.QueryStrings; + +public sealed class SparseFieldSetTests : IClassFixture, QueryStringDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, QueryStringDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly QueryStringFakers _fakers = new(); + + public SparseFieldSetTests(IntegrationTestContext, QueryStringDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseController(); + } + + [Fact] + public async Task Can_select_attribute_in_primary_resources() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new QueryStringsClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["fields[nodes]"] = "name" + }); + + // Act + NodeCollectionResponseDocument? response = await apiClient.Nodes.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(1); + response.Data.ElementAt(0).Id.Should().Be(node.StringId); + + response.Data.ElementAt(0).Attributes.RefShould().NotBeNull().And.Subject.With(attributes => + { + attributes.Name.Should().Be(node.Name); + attributes.Comment.Should().BeNull(); + }); + + response.Data.ElementAt(0).Relationships.Should().BeNull(); + } + + [Fact] + public async Task Can_select_fields_in_primary_resource() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new QueryStringsClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["fields[nodes]"] = "comment,parent" + }); + + // Act + PrimaryNodeResponseDocument? response = await apiClient.Nodes[node.StringId!].GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().NotBeNull(); + response.Data.Id.Should().Be(node.StringId); + response.Data.Attributes.Should().NotBeNull(); + response.Data.Attributes.Name.Should().BeNull(); + response.Data.Attributes.Comment.Should().Be(node.Comment); + response.Data.Relationships.Should().NotBeNull(); + response.Data.Relationships.Parent.Should().NotBeNull(); + response.Data.Relationships.Children.Should().BeNull(); + } + + [Fact] + public async Task Can_select_fields_in_secondary_resources() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Children = _fakers.Node.GenerateSet(1); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new QueryStringsClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["fields[nodes]"] = "comment,children" + }); + + // Act + NodeCollectionResponseDocument? response = await apiClient.Nodes[node.StringId!].Children.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(1); + response.Data.ElementAt(0).Id.Should().Be(node.Children.ElementAt(0).StringId); + + response.Data.ElementAt(0).Attributes.RefShould().NotBeNull().And.Subject.With(attributes => + { + attributes.Name.Should().BeNull(); + attributes.Comment.Should().Be(node.Children.ElementAt(0).Comment); + }); + + response.Data.ElementAt(0).Relationships.RefShould().NotBeNull().And.Subject.With(relationships => + { + relationships.Parent.Should().BeNull(); + relationships.Children.Should().NotBeNull(); + }); + } + + [Fact] + public async Task Can_select_fields_in_secondary_resource() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Parent = _fakers.Node.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new QueryStringsClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["fields[nodes]"] = "comment,children" + }); + + // Act + NullableSecondaryNodeResponseDocument? response = await apiClient.Nodes[node.StringId!].Parent.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().NotBeNull(); + response.Data.Id.Should().Be(node.Parent.StringId); + response.Data.Attributes.Should().NotBeNull(); + response.Data.Attributes.Name.Should().BeNull(); + response.Data.Attributes.Comment.Should().Be(node.Parent.Comment); + response.Data.Relationships.Should().NotBeNull(); + response.Data.Relationships.Parent.Should().BeNull(); + response.Data.Relationships.Children.Should().NotBeNull(); + } + + [Fact] + public async Task Can_select_empty_fieldset() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new QueryStringsClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["fields[nodes]"] = null + }); + + // Act + PrimaryNodeResponseDocument? response = await apiClient.Nodes[node.StringId!].GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().NotBeNull(); + response.Data.Id.Should().Be(node.StringId); + response.Data.Attributes.Should().BeNull(); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bathrooms/BathroomsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bathrooms/BathroomsRequestBuilder.cs new file mode 100644 index 0000000000..34608e41f5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bathrooms/BathroomsRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.Item; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms +{ + /// + /// Builds and executes requests for operations under \bathrooms + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BathroomsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.bathrooms.item collection + /// The identifier of the bathroom to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.Item.BathroomsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.Item.BathroomsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public BathroomsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bathrooms{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public BathroomsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bathrooms{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of bathrooms. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BathroomCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new bathroom. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateBathroomRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryBathroomResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of bathrooms. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new bathroom. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateBathroomRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.BathroomsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.BathroomsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of bathrooms. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BathroomsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BathroomsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new bathroom. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BathroomsRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bathrooms/Item/BathroomsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bathrooms/Item/BathroomsItemRequestBuilder.cs new file mode 100644 index 0000000000..7bad7a5678 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bathrooms/Item/BathroomsItemRequestBuilder.cs @@ -0,0 +1,223 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.Item.Relationships; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.Item.Residence; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.Item +{ + /// + /// Builds and executes requests for operations under \bathrooms\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BathroomsItemRequestBuilder : BaseRequestBuilder + { + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.Item.Residence.ResidenceRequestBuilder Residence + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.Item.Residence.ResidenceRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public BathroomsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bathrooms/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public BathroomsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bathrooms/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing bathroom by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual bathroom by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryBathroomResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing bathroom. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateBathroomRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryBathroomResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing bathroom by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual bathroom by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing bathroom. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateBathroomRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.Item.BathroomsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.Item.BathroomsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual bathroom by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BathroomsItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BathroomsItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing bathroom. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BathroomsItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bathrooms/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bathrooms/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..3b90f465c1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bathrooms/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.Item.Relationships.Residence; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \bathrooms\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.Item.Relationships.Residence.ResidenceRequestBuilder Residence + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.Item.Relationships.Residence.ResidenceRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bathrooms/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bathrooms/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bathrooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bathrooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs new file mode 100644 index 0000000000..1a54eff2ec --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bathrooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs @@ -0,0 +1,168 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.Item.Relationships.Residence +{ + /// + /// Builds and executes requests for operations under \bathrooms\{id}\relationships\residence + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bathrooms/{id}/relationships/residence{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bathrooms/{id}/relationships/residence{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related residence identity of an individual bathroom's residence relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns an existing residence to the residence relationship of an individual bathroom. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related residence identity of an individual bathroom's residence relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns an existing residence to the residence relationship of an individual bathroom. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.Item.Relationships.Residence.ResidenceRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.Item.Relationships.Residence.ResidenceRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related residence identity of an individual bathroom's residence relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bathrooms/Item/Residence/ResidenceRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bathrooms/Item/Residence/ResidenceRequestBuilder.cs new file mode 100644 index 0000000000..33d9f5449c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bathrooms/Item/Residence/ResidenceRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.Item.Residence +{ + /// + /// Builds and executes requests for operations under \bathrooms\{id}\residence + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bathrooms/{id}/residence{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bathrooms/{id}/residence{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related residence of an individual bathroom's residence relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.SecondaryResidenceResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related residence of an individual bathroom's residence relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.Item.Residence.ResidenceRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.Item.Residence.ResidenceRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related residence of an individual bathroom's residence relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bedrooms/BedroomsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bedrooms/BedroomsRequestBuilder.cs new file mode 100644 index 0000000000..1840a6c635 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bedrooms/BedroomsRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.Item; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms +{ + /// + /// Builds and executes requests for operations under \bedrooms + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BedroomsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.bedrooms.item collection + /// The identifier of the bedroom to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.Item.BedroomsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.Item.BedroomsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public BedroomsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bedrooms{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public BedroomsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bedrooms{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of bedrooms. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BedroomCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new bedroom. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateBedroomRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryBedroomResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of bedrooms. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new bedroom. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateBedroomRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.BedroomsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.BedroomsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of bedrooms. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BedroomsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BedroomsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new bedroom. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BedroomsRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bedrooms/Item/BedroomsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bedrooms/Item/BedroomsItemRequestBuilder.cs new file mode 100644 index 0000000000..57973ce98f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bedrooms/Item/BedroomsItemRequestBuilder.cs @@ -0,0 +1,223 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.Item.Relationships; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.Item.Residence; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.Item +{ + /// + /// Builds and executes requests for operations under \bedrooms\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BedroomsItemRequestBuilder : BaseRequestBuilder + { + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.Item.Residence.ResidenceRequestBuilder Residence + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.Item.Residence.ResidenceRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public BedroomsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bedrooms/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public BedroomsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bedrooms/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing bedroom by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual bedroom by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryBedroomResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing bedroom. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateBedroomRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryBedroomResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing bedroom by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual bedroom by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing bedroom. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateBedroomRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.Item.BedroomsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.Item.BedroomsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual bedroom by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BedroomsItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BedroomsItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing bedroom. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BedroomsItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bedrooms/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bedrooms/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..598e388d8a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bedrooms/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.Item.Relationships.Residence; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \bedrooms\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.Item.Relationships.Residence.ResidenceRequestBuilder Residence + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.Item.Relationships.Residence.ResidenceRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bedrooms/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bedrooms/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bedrooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bedrooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs new file mode 100644 index 0000000000..d29f2e5942 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bedrooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs @@ -0,0 +1,168 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.Item.Relationships.Residence +{ + /// + /// Builds and executes requests for operations under \bedrooms\{id}\relationships\residence + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bedrooms/{id}/relationships/residence{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bedrooms/{id}/relationships/residence{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related residence identity of an individual bedroom's residence relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns an existing residence to the residence relationship of an individual bedroom. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related residence identity of an individual bedroom's residence relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns an existing residence to the residence relationship of an individual bedroom. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.Item.Relationships.Residence.ResidenceRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.Item.Relationships.Residence.ResidenceRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related residence identity of an individual bedroom's residence relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bedrooms/Item/Residence/ResidenceRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bedrooms/Item/Residence/ResidenceRequestBuilder.cs new file mode 100644 index 0000000000..6135d54b25 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Bedrooms/Item/Residence/ResidenceRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.Item.Residence +{ + /// + /// Builds and executes requests for operations under \bedrooms\{id}\residence + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bedrooms/{id}/residence{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bedrooms/{id}/residence{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related residence of an individual bedroom's residence relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.SecondaryResidenceResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related residence of an individual bedroom's residence relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.Item.Residence.ResidenceRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.Item.Residence.ResidenceRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related residence of an individual bedroom's residence relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Buildings/BuildingsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Buildings/BuildingsRequestBuilder.cs new file mode 100644 index 0000000000..a7b82a36b4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Buildings/BuildingsRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Buildings.Item; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Buildings +{ + /// + /// Builds and executes requests for operations under \buildings + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BuildingsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.buildings.item collection + /// The identifier of the building to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Buildings.Item.BuildingsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Buildings.Item.BuildingsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public BuildingsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/buildings{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public BuildingsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/buildings{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of buildings. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BuildingCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new building. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateBuildingRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryBuildingResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of buildings. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new building. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateBuildingRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Buildings.BuildingsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Buildings.BuildingsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of buildings. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BuildingsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BuildingsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new building. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BuildingsRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Buildings/Item/BuildingsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Buildings/Item/BuildingsItemRequestBuilder.cs new file mode 100644 index 0000000000..21def4f450 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Buildings/Item/BuildingsItemRequestBuilder.cs @@ -0,0 +1,209 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Buildings.Item +{ + /// + /// Builds and executes requests for operations under \buildings\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BuildingsItemRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public BuildingsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/buildings/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public BuildingsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/buildings/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing building by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual building by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryBuildingResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing building. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateBuildingRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryBuildingResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing building by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual building by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing building. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateBuildingRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Buildings.Item.BuildingsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Buildings.Item.BuildingsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual building by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BuildingsItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BuildingsItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing building. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BuildingsItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/CyclePaths/CyclePathsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/CyclePaths/CyclePathsRequestBuilder.cs new file mode 100644 index 0000000000..33f67a3fc6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/CyclePaths/CyclePathsRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.CyclePaths.Item; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.CyclePaths +{ + /// + /// Builds and executes requests for operations under \cyclePaths + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class CyclePathsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.cyclePaths.item collection + /// The identifier of the cyclePath to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.CyclePaths.Item.CyclePathsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.CyclePaths.Item.CyclePathsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public CyclePathsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/cyclePaths{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public CyclePathsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/cyclePaths{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of cyclePaths. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CyclePathCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new cyclePath. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateCyclePathRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryCyclePathResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of cyclePaths. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new cyclePath. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateCyclePathRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.CyclePaths.CyclePathsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.CyclePaths.CyclePathsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of cyclePaths. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class CyclePathsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class CyclePathsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new cyclePath. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class CyclePathsRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/CyclePaths/Item/CyclePathsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/CyclePaths/Item/CyclePathsItemRequestBuilder.cs new file mode 100644 index 0000000000..04478d64d4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/CyclePaths/Item/CyclePathsItemRequestBuilder.cs @@ -0,0 +1,209 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.CyclePaths.Item +{ + /// + /// Builds and executes requests for operations under \cyclePaths\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class CyclePathsItemRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public CyclePathsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/cyclePaths/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public CyclePathsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/cyclePaths/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing cyclePath by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual cyclePath by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryCyclePathResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing cyclePath. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateCyclePathRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryCyclePathResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing cyclePath by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual cyclePath by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing cyclePath. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateCyclePathRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.CyclePaths.Item.CyclePathsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.CyclePaths.Item.CyclePathsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual cyclePath by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class CyclePathsItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class CyclePathsItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing cyclePath. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class CyclePathsItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Districts/DistrictsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Districts/DistrictsRequestBuilder.cs new file mode 100644 index 0000000000..84fde078ac --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Districts/DistrictsRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts +{ + /// + /// Builds and executes requests for operations under \districts + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class DistrictsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.districts.item collection + /// The identifier of the district to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.DistrictsItemRequestBuilder this[Guid position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.DistrictsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public DistrictsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public DistrictsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of districts. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DistrictCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new district. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateDistrictRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryDistrictResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of districts. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new district. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateDistrictRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.DistrictsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.DistrictsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of districts. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class DistrictsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class DistrictsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new district. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class DistrictsRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Districts/Item/Buildings/BuildingsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Districts/Item/Buildings/BuildingsRequestBuilder.cs new file mode 100644 index 0000000000..97697a878c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Districts/Item/Buildings/BuildingsRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Buildings +{ + /// + /// Builds and executes requests for operations under \districts\{id}\buildings + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BuildingsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public BuildingsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts/{id}/buildings{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public BuildingsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts/{id}/buildings{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related buildings of an individual district's buildings relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BuildingCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related buildings of an individual district's buildings relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Buildings.BuildingsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Buildings.BuildingsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related buildings of an individual district's buildings relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BuildingsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BuildingsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Districts/Item/DistrictsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Districts/Item/DistrictsItemRequestBuilder.cs new file mode 100644 index 0000000000..a53f46f4cd --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Districts/Item/DistrictsItemRequestBuilder.cs @@ -0,0 +1,230 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Buildings; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Relationships; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Roads; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item +{ + /// + /// Builds and executes requests for operations under \districts\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class DistrictsItemRequestBuilder : BaseRequestBuilder + { + /// The buildings property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Buildings.BuildingsRequestBuilder Buildings + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Buildings.BuildingsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The roads property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Roads.RoadsRequestBuilder Roads + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Roads.RoadsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public DistrictsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public DistrictsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing district by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual district by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryDistrictResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing district. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateDistrictRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryDistrictResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing district by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual district by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing district. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateDistrictRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.DistrictsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.DistrictsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual district by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class DistrictsItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class DistrictsItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing district. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class DistrictsItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Districts/Item/Relationships/Buildings/BuildingsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Districts/Item/Relationships/Buildings/BuildingsRequestBuilder.cs new file mode 100644 index 0000000000..4748494921 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Districts/Item/Relationships/Buildings/BuildingsRequestBuilder.cs @@ -0,0 +1,248 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Relationships.Buildings +{ + /// + /// Builds and executes requests for operations under \districts\{id}\relationships\buildings + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BuildingsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public BuildingsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts/{id}/relationships/buildings{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public BuildingsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts/{id}/relationships/buildings{?query*}", rawUrl) + { + } + + /// + /// Removes existing buildings from the buildings relationship of an individual district. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task DeleteAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyBuildingInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToDeleteRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related building identities of an individual district's buildings relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BuildingIdentifierCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns existing buildings to the buildings relationship of an individual district. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyBuildingInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Adds existing buildings to the buildings relationship of an individual district. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyBuildingInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Removes existing buildings from the buildings relationship of an individual district. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyBuildingInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Retrieves the related building identities of an individual district's buildings relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns existing buildings to the buildings relationship of an individual district. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyBuildingInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Adds existing buildings to the buildings relationship of an individual district. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyBuildingInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Relationships.Buildings.BuildingsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Relationships.Buildings.BuildingsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related building identities of an individual district's buildings relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BuildingsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BuildingsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Districts/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Districts/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..4d174d56d3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Districts/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,52 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Relationships.Buildings; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Relationships.Roads; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \districts\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The buildings property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Relationships.Buildings.BuildingsRequestBuilder Buildings + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Relationships.Buildings.BuildingsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The roads property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Relationships.Roads.RoadsRequestBuilder Roads + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Relationships.Roads.RoadsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Districts/Item/Relationships/Roads/RoadsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Districts/Item/Relationships/Roads/RoadsRequestBuilder.cs new file mode 100644 index 0000000000..99cbc09bde --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Districts/Item/Relationships/Roads/RoadsRequestBuilder.cs @@ -0,0 +1,248 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Relationships.Roads +{ + /// + /// Builds and executes requests for operations under \districts\{id}\relationships\roads + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoadsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RoadsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts/{id}/relationships/roads{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RoadsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts/{id}/relationships/roads{?query*}", rawUrl) + { + } + + /// + /// Removes existing roads from the roads relationship of an individual district. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task DeleteAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoadInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToDeleteRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related road identities of an individual district's roads relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoadIdentifierCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns existing roads to the roads relationship of an individual district. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoadInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Adds existing roads to the roads relationship of an individual district. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoadInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Removes existing roads from the roads relationship of an individual district. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoadInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Retrieves the related road identities of an individual district's roads relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns existing roads to the roads relationship of an individual district. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoadInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Adds existing roads to the roads relationship of an individual district. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoadInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Relationships.Roads.RoadsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Relationships.Roads.RoadsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related road identities of an individual district's roads relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoadsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoadsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Districts/Item/Roads/RoadsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Districts/Item/Roads/RoadsRequestBuilder.cs new file mode 100644 index 0000000000..634873f4be --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Districts/Item/Roads/RoadsRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Roads +{ + /// + /// Builds and executes requests for operations under \districts\{id}\roads + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoadsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RoadsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts/{id}/roads{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RoadsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts/{id}/roads{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related roads of an individual district's roads relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoadCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related roads of an individual district's roads relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Roads.RoadsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.Item.Roads.RoadsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related roads of an individual district's roads relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoadsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoadsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/FamilyHomes/FamilyHomesRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/FamilyHomes/FamilyHomesRequestBuilder.cs new file mode 100644 index 0000000000..74cc7fcfec --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/FamilyHomes/FamilyHomesRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.Item; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes +{ + /// + /// Builds and executes requests for operations under \familyHomes + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class FamilyHomesRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.familyHomes.item collection + /// The identifier of the familyHome to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.Item.FamilyHomesItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.Item.FamilyHomesItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public FamilyHomesRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public FamilyHomesRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of familyHomes. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.FamilyHomeCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new familyHome. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateFamilyHomeRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryFamilyHomeResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of familyHomes. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new familyHome. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateFamilyHomeRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.FamilyHomesRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.FamilyHomesRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of familyHomes. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class FamilyHomesRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class FamilyHomesRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new familyHome. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class FamilyHomesRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/FamilyHomes/Item/FamilyHomesItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/FamilyHomes/Item/FamilyHomesItemRequestBuilder.cs new file mode 100644 index 0000000000..5cd86b9293 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/FamilyHomes/Item/FamilyHomesItemRequestBuilder.cs @@ -0,0 +1,223 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.Item.Relationships; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.Item.Rooms; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.Item +{ + /// + /// Builds and executes requests for operations under \familyHomes\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class FamilyHomesItemRequestBuilder : BaseRequestBuilder + { + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The rooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.Item.Rooms.RoomsRequestBuilder Rooms + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.Item.Rooms.RoomsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public FamilyHomesItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public FamilyHomesItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing familyHome by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual familyHome by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryFamilyHomeResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing familyHome. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateFamilyHomeRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryFamilyHomeResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing familyHome by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual familyHome by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing familyHome. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateFamilyHomeRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.Item.FamilyHomesItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.Item.FamilyHomesItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual familyHome by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class FamilyHomesItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class FamilyHomesItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing familyHome. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class FamilyHomesItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/FamilyHomes/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/FamilyHomes/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..07f1485722 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/FamilyHomes/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.Item.Relationships.Rooms; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \familyHomes\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The rooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.Item.Relationships.Rooms.RoomsRequestBuilder Rooms + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.Item.Relationships.Rooms.RoomsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/FamilyHomes/Item/Relationships/Rooms/RoomsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/FamilyHomes/Item/Relationships/Rooms/RoomsRequestBuilder.cs new file mode 100644 index 0000000000..ec7dc70718 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/FamilyHomes/Item/Relationships/Rooms/RoomsRequestBuilder.cs @@ -0,0 +1,248 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.Item.Relationships.Rooms +{ + /// + /// Builds and executes requests for operations under \familyHomes\{id}\relationships\rooms + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes/{id}/relationships/rooms{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes/{id}/relationships/rooms{?query*}", rawUrl) + { + } + + /// + /// Removes existing rooms from the rooms relationship of an individual familyHome. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task DeleteAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToDeleteRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related room identities of an individual familyHome's rooms relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomIdentifierCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns existing rooms to the rooms relationship of an individual familyHome. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Adds existing rooms to the rooms relationship of an individual familyHome. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Removes existing rooms from the rooms relationship of an individual familyHome. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Retrieves the related room identities of an individual familyHome's rooms relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns existing rooms to the rooms relationship of an individual familyHome. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Adds existing rooms to the rooms relationship of an individual familyHome. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.Item.Relationships.Rooms.RoomsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.Item.Relationships.Rooms.RoomsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related room identities of an individual familyHome's rooms relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/FamilyHomes/Item/Rooms/RoomsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/FamilyHomes/Item/Rooms/RoomsRequestBuilder.cs new file mode 100644 index 0000000000..1bff7a15bb --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/FamilyHomes/Item/Rooms/RoomsRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.Item.Rooms +{ + /// + /// Builds and executes requests for operations under \familyHomes\{id}\rooms + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes/{id}/rooms{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes/{id}/rooms{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related rooms of an individual familyHome's rooms relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related rooms of an individual familyHome's rooms relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.Item.Rooms.RoomsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.Item.Rooms.RoomsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related rooms of an individual familyHome's rooms relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Kitchens/Item/KitchensItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Kitchens/Item/KitchensItemRequestBuilder.cs new file mode 100644 index 0000000000..c333387544 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Kitchens/Item/KitchensItemRequestBuilder.cs @@ -0,0 +1,223 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.Item.Relationships; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.Item.Residence; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.Item +{ + /// + /// Builds and executes requests for operations under \kitchens\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class KitchensItemRequestBuilder : BaseRequestBuilder + { + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.Item.Residence.ResidenceRequestBuilder Residence + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.Item.Residence.ResidenceRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public KitchensItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/kitchens/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public KitchensItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/kitchens/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing kitchen by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual kitchen by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryKitchenResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing kitchen. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateKitchenRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryKitchenResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing kitchen by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual kitchen by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing kitchen. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateKitchenRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.Item.KitchensItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.Item.KitchensItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual kitchen by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class KitchensItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class KitchensItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing kitchen. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class KitchensItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Kitchens/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Kitchens/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..c4e1dd41e5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Kitchens/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.Item.Relationships.Residence; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \kitchens\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.Item.Relationships.Residence.ResidenceRequestBuilder Residence + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.Item.Relationships.Residence.ResidenceRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/kitchens/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/kitchens/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Kitchens/Item/Relationships/Residence/ResidenceRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Kitchens/Item/Relationships/Residence/ResidenceRequestBuilder.cs new file mode 100644 index 0000000000..518743a34d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Kitchens/Item/Relationships/Residence/ResidenceRequestBuilder.cs @@ -0,0 +1,168 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.Item.Relationships.Residence +{ + /// + /// Builds and executes requests for operations under \kitchens\{id}\relationships\residence + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/kitchens/{id}/relationships/residence{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/kitchens/{id}/relationships/residence{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related residence identity of an individual kitchen's residence relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns an existing residence to the residence relationship of an individual kitchen. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related residence identity of an individual kitchen's residence relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns an existing residence to the residence relationship of an individual kitchen. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.Item.Relationships.Residence.ResidenceRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.Item.Relationships.Residence.ResidenceRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related residence identity of an individual kitchen's residence relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Kitchens/Item/Residence/ResidenceRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Kitchens/Item/Residence/ResidenceRequestBuilder.cs new file mode 100644 index 0000000000..3aeba693c8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Kitchens/Item/Residence/ResidenceRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.Item.Residence +{ + /// + /// Builds and executes requests for operations under \kitchens\{id}\residence + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/kitchens/{id}/residence{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/kitchens/{id}/residence{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related residence of an individual kitchen's residence relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.SecondaryResidenceResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related residence of an individual kitchen's residence relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.Item.Residence.ResidenceRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.Item.Residence.ResidenceRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related residence of an individual kitchen's residence relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Kitchens/KitchensRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Kitchens/KitchensRequestBuilder.cs new file mode 100644 index 0000000000..9550379dbc --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Kitchens/KitchensRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.Item; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens +{ + /// + /// Builds and executes requests for operations under \kitchens + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class KitchensRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.kitchens.item collection + /// The identifier of the kitchen to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.Item.KitchensItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.Item.KitchensItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public KitchensRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/kitchens{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public KitchensRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/kitchens{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of kitchens. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.KitchenCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new kitchen. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateKitchenRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryKitchenResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of kitchens. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new kitchen. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateKitchenRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.KitchensRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.KitchensRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of kitchens. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class KitchensRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class KitchensRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new kitchen. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class KitchensRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/LivingRooms/Item/LivingRoomsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/LivingRooms/Item/LivingRoomsItemRequestBuilder.cs new file mode 100644 index 0000000000..707839f5b5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/LivingRooms/Item/LivingRoomsItemRequestBuilder.cs @@ -0,0 +1,223 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.Item.Relationships; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.Item.Residence; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.Item +{ + /// + /// Builds and executes requests for operations under \livingRooms\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class LivingRoomsItemRequestBuilder : BaseRequestBuilder + { + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.Item.Residence.ResidenceRequestBuilder Residence + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.Item.Residence.ResidenceRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public LivingRoomsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/livingRooms/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public LivingRoomsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/livingRooms/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing livingRoom by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual livingRoom by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryLivingRoomResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing livingRoom. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateLivingRoomRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryLivingRoomResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing livingRoom by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual livingRoom by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing livingRoom. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateLivingRoomRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.Item.LivingRoomsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.Item.LivingRoomsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual livingRoom by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class LivingRoomsItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class LivingRoomsItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing livingRoom. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class LivingRoomsItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/LivingRooms/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/LivingRooms/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..f94fee1287 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/LivingRooms/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.Item.Relationships.Residence; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \livingRooms\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.Item.Relationships.Residence.ResidenceRequestBuilder Residence + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.Item.Relationships.Residence.ResidenceRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/livingRooms/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/livingRooms/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/LivingRooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/LivingRooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs new file mode 100644 index 0000000000..04baa480d3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/LivingRooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs @@ -0,0 +1,168 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.Item.Relationships.Residence +{ + /// + /// Builds and executes requests for operations under \livingRooms\{id}\relationships\residence + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/livingRooms/{id}/relationships/residence{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/livingRooms/{id}/relationships/residence{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related residence identity of an individual livingRoom's residence relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns an existing residence to the residence relationship of an individual livingRoom. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related residence identity of an individual livingRoom's residence relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns an existing residence to the residence relationship of an individual livingRoom. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.Item.Relationships.Residence.ResidenceRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.Item.Relationships.Residence.ResidenceRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related residence identity of an individual livingRoom's residence relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/LivingRooms/Item/Residence/ResidenceRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/LivingRooms/Item/Residence/ResidenceRequestBuilder.cs new file mode 100644 index 0000000000..94c62f4484 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/LivingRooms/Item/Residence/ResidenceRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.Item.Residence +{ + /// + /// Builds and executes requests for operations under \livingRooms\{id}\residence + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/livingRooms/{id}/residence{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/livingRooms/{id}/residence{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related residence of an individual livingRoom's residence relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.SecondaryResidenceResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related residence of an individual livingRoom's residence relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.Item.Residence.ResidenceRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.Item.Residence.ResidenceRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related residence of an individual livingRoom's residence relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/LivingRooms/LivingRoomsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/LivingRooms/LivingRoomsRequestBuilder.cs new file mode 100644 index 0000000000..fd88e306a4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/LivingRooms/LivingRoomsRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.Item; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms +{ + /// + /// Builds and executes requests for operations under \livingRooms + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class LivingRoomsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.livingRooms.item collection + /// The identifier of the livingRoom to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.Item.LivingRoomsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.Item.LivingRoomsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public LivingRoomsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/livingRooms{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public LivingRoomsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/livingRooms{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of livingRooms. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.LivingRoomCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new livingRoom. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateLivingRoomRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryLivingRoomResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of livingRooms. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new livingRoom. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateLivingRoomRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.LivingRoomsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.LivingRoomsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of livingRooms. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class LivingRoomsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class LivingRoomsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new livingRoom. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class LivingRoomsRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Mansions/Item/MansionsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Mansions/Item/MansionsItemRequestBuilder.cs new file mode 100644 index 0000000000..9f2408c428 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Mansions/Item/MansionsItemRequestBuilder.cs @@ -0,0 +1,230 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Relationships; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Rooms; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Staff; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item +{ + /// + /// Builds and executes requests for operations under \mansions\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class MansionsItemRequestBuilder : BaseRequestBuilder + { + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The rooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Rooms.RoomsRequestBuilder Rooms + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Rooms.RoomsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The staff property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Staff.StaffRequestBuilder Staff + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Staff.StaffRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public MansionsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public MansionsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing mansion by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual mansion by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryMansionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing mansion. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateMansionRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryMansionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing mansion by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual mansion by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing mansion. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateMansionRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.MansionsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.MansionsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual mansion by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class MansionsItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class MansionsItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing mansion. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class MansionsItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Mansions/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Mansions/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..0a490103df --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Mansions/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,52 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Relationships.Rooms; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Relationships.Staff; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \mansions\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The rooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Relationships.Rooms.RoomsRequestBuilder Rooms + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Relationships.Rooms.RoomsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The staff property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Relationships.Staff.StaffRequestBuilder Staff + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Relationships.Staff.StaffRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Mansions/Item/Relationships/Rooms/RoomsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Mansions/Item/Relationships/Rooms/RoomsRequestBuilder.cs new file mode 100644 index 0000000000..096d7a183e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Mansions/Item/Relationships/Rooms/RoomsRequestBuilder.cs @@ -0,0 +1,248 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Relationships.Rooms +{ + /// + /// Builds and executes requests for operations under \mansions\{id}\relationships\rooms + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions/{id}/relationships/rooms{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions/{id}/relationships/rooms{?query*}", rawUrl) + { + } + + /// + /// Removes existing rooms from the rooms relationship of an individual mansion. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task DeleteAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToDeleteRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related room identities of an individual mansion's rooms relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomIdentifierCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns existing rooms to the rooms relationship of an individual mansion. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Adds existing rooms to the rooms relationship of an individual mansion. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Removes existing rooms from the rooms relationship of an individual mansion. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Retrieves the related room identities of an individual mansion's rooms relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns existing rooms to the rooms relationship of an individual mansion. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Adds existing rooms to the rooms relationship of an individual mansion. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Relationships.Rooms.RoomsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Relationships.Rooms.RoomsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related room identities of an individual mansion's rooms relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Mansions/Item/Relationships/Staff/StaffRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Mansions/Item/Relationships/Staff/StaffRequestBuilder.cs new file mode 100644 index 0000000000..219198b689 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Mansions/Item/Relationships/Staff/StaffRequestBuilder.cs @@ -0,0 +1,248 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Relationships.Staff +{ + /// + /// Builds and executes requests for operations under \mansions\{id}\relationships\staff + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class StaffRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public StaffRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions/{id}/relationships/staff{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public StaffRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions/{id}/relationships/staff{?query*}", rawUrl) + { + } + + /// + /// Removes existing staffMembers from the staff relationship of an individual mansion. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task DeleteAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyStaffMemberInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToDeleteRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related staffMember identities of an individual mansion's staff relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.StaffMemberIdentifierCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns existing staffMembers to the staff relationship of an individual mansion. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyStaffMemberInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Adds existing staffMembers to the staff relationship of an individual mansion. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyStaffMemberInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Removes existing staffMembers from the staff relationship of an individual mansion. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyStaffMemberInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Retrieves the related staffMember identities of an individual mansion's staff relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns existing staffMembers to the staff relationship of an individual mansion. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyStaffMemberInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Adds existing staffMembers to the staff relationship of an individual mansion. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyStaffMemberInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Relationships.Staff.StaffRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Relationships.Staff.StaffRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related staffMember identities of an individual mansion's staff relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class StaffRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class StaffRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Mansions/Item/Rooms/RoomsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Mansions/Item/Rooms/RoomsRequestBuilder.cs new file mode 100644 index 0000000000..e14200cf8e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Mansions/Item/Rooms/RoomsRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Rooms +{ + /// + /// Builds and executes requests for operations under \mansions\{id}\rooms + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions/{id}/rooms{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions/{id}/rooms{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related rooms of an individual mansion's rooms relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related rooms of an individual mansion's rooms relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Rooms.RoomsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Rooms.RoomsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related rooms of an individual mansion's rooms relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Mansions/Item/Staff/StaffRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Mansions/Item/Staff/StaffRequestBuilder.cs new file mode 100644 index 0000000000..6215a14033 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Mansions/Item/Staff/StaffRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Staff +{ + /// + /// Builds and executes requests for operations under \mansions\{id}\staff + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class StaffRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public StaffRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions/{id}/staff{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public StaffRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions/{id}/staff{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related staffMembers of an individual mansion's staff relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.StaffMemberCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related staffMembers of an individual mansion's staff relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Staff.StaffRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.Staff.StaffRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related staffMembers of an individual mansion's staff relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class StaffRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class StaffRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Mansions/MansionsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Mansions/MansionsRequestBuilder.cs new file mode 100644 index 0000000000..1230c0f5ad --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Mansions/MansionsRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions +{ + /// + /// Builds and executes requests for operations under \mansions + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class MansionsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.mansions.item collection + /// The identifier of the mansion to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.MansionsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.Item.MansionsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public MansionsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public MansionsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of mansions. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.MansionCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new mansion. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateMansionRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryMansionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of mansions. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new mansion. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateMansionRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.MansionsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.MansionsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of mansions. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class MansionsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class MansionsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new mansion. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class MansionsRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AtomicOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AtomicOperation.cs new file mode 100644 index 0000000000..6a330e8052 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AtomicOperation.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AtomicOperation : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The openapiDiscriminator property + public string? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AtomicOperation() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AtomicOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AtomicOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteStringValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AtomicResult.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AtomicResult.cs new file mode 100644 index 0000000000..72c6061598 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AtomicResult.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AtomicResult : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AtomicResult() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AtomicResult CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AtomicResult(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInBathroomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInBathroomResponse.cs new file mode 100644 index 0000000000..f475aa09f9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInBathroomResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInBathroomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// The hasBath property + public bool? HasBath + { + get { return BackingStore?.Get("hasBath"); } + set { BackingStore?.Set("hasBath", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInBathroomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInBathroomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasBath", n => { HasBath = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasBath", HasBath); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInBedroomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInBedroomResponse.cs new file mode 100644 index 0000000000..52408928f7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInBedroomResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInBedroomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// The bedCount property + public int? BedCount + { + get { return BackingStore?.Get("bedCount"); } + set { BackingStore?.Set("bedCount", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInBedroomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInBedroomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "bedCount", n => { BedCount = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("bedCount", BedCount); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInBuildingResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInBuildingResponse.cs new file mode 100644 index 0000000000..0d95aa7196 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInBuildingResponse.cs @@ -0,0 +1,66 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInBuildingResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The surfaceInSquareMeters property + public int? SurfaceInSquareMeters + { + get { return BackingStore?.Get("surfaceInSquareMeters"); } + set { BackingStore?.Set("surfaceInSquareMeters", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInBuildingResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInFamilyHomeResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInMansionResponse(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInResidenceResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInBuildingResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "surfaceInSquareMeters", n => { SurfaceInSquareMeters = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("surfaceInSquareMeters", SurfaceInSquareMeters); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateBathroomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateBathroomRequest.cs new file mode 100644 index 0000000000..301d794d42 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateBathroomRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateBathroomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// The hasBath property + public bool? HasBath + { + get { return BackingStore?.Get("hasBath"); } + set { BackingStore?.Set("hasBath", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateBathroomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateBathroomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasBath", n => { HasBath = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasBath", HasBath); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateBedroomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateBedroomRequest.cs new file mode 100644 index 0000000000..8d75a4efec --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateBedroomRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateBedroomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// The bedCount property + public int? BedCount + { + get { return BackingStore?.Get("bedCount"); } + set { BackingStore?.Set("bedCount", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateBedroomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateBedroomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "bedCount", n => { BedCount = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("bedCount", BedCount); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateBuildingRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateBuildingRequest.cs new file mode 100644 index 0000000000..cc34a8ab0a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateBuildingRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateBuildingRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The surfaceInSquareMeters property + public int? SurfaceInSquareMeters + { + get { return BackingStore?.Get("surfaceInSquareMeters"); } + set { BackingStore?.Set("surfaceInSquareMeters", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateBuildingRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateBuildingRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "surfaceInSquareMeters", n => { SurfaceInSquareMeters = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("surfaceInSquareMeters", SurfaceInSquareMeters); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateCyclePathRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateCyclePathRequest.cs new file mode 100644 index 0000000000..a94f35bd20 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateCyclePathRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateCyclePathRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateRoadRequest, IParsable + #pragma warning restore CS1591 + { + /// The hasLaneForPedestrians property + public bool? HasLaneForPedestrians + { + get { return BackingStore?.Get("hasLaneForPedestrians"); } + set { BackingStore?.Set("hasLaneForPedestrians", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateCyclePathRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateCyclePathRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasLaneForPedestrians", n => { HasLaneForPedestrians = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasLaneForPedestrians", HasLaneForPedestrians); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateDistrictRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateDistrictRequest.cs new file mode 100644 index 0000000000..8eef5f29d4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateDistrictRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateDistrictRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateDistrictRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateDistrictRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateFamilyHomeRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateFamilyHomeRequest.cs new file mode 100644 index 0000000000..097c47099b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateFamilyHomeRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateFamilyHomeRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// The floorCount property + public int? FloorCount + { + get { return BackingStore?.Get("floorCount"); } + set { BackingStore?.Set("floorCount", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateFamilyHomeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateFamilyHomeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "floorCount", n => { FloorCount = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("floorCount", FloorCount); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateKitchenRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateKitchenRequest.cs new file mode 100644 index 0000000000..60f83f5faa --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateKitchenRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateKitchenRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// The hasPantry property + public bool? HasPantry + { + get { return BackingStore?.Get("hasPantry"); } + set { BackingStore?.Set("hasPantry", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateKitchenRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateKitchenRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasPantry", n => { HasPantry = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasPantry", HasPantry); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateLivingRoomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateLivingRoomRequest.cs new file mode 100644 index 0000000000..99d12264dd --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateLivingRoomRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateLivingRoomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// The hasDiningTable property + public bool? HasDiningTable + { + get { return BackingStore?.Get("hasDiningTable"); } + set { BackingStore?.Set("hasDiningTable", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateLivingRoomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateLivingRoomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasDiningTable", n => { HasDiningTable = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasDiningTable", HasDiningTable); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateMansionRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateMansionRequest.cs new file mode 100644 index 0000000000..fda98370a5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateMansionRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateMansionRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// The ownerName property + public string? OwnerName + { + get { return BackingStore?.Get("ownerName"); } + set { BackingStore?.Set("ownerName", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateMansionRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateMansionRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "ownerName", n => { OwnerName = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("ownerName", OwnerName); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateRequest.cs new file mode 100644 index 0000000000..250635de7e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateRequest.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateBathroomRequest(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateBedroomRequest(), + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateBuildingRequest(), + "cyclePaths" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateCyclePathRequest(), + "districts" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateDistrictRequest(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateFamilyHomeRequest(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateKitchenRequest(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateLivingRoomRequest(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateMansionRequest(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateResidenceRequest(), + "roads" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateRoadRequest(), + "rooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateRoomRequest(), + "staffMembers" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateStaffMemberRequest(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateToiletRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateResidenceRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateResidenceRequest.cs new file mode 100644 index 0000000000..4978f20cd8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateResidenceRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateResidenceRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateBuildingRequest, IParsable + #pragma warning restore CS1591 + { + /// The numberOfResidents property + public int? NumberOfResidents + { + get { return BackingStore?.Get("numberOfResidents"); } + set { BackingStore?.Set("numberOfResidents", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateResidenceRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateResidenceRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "numberOfResidents", n => { NumberOfResidents = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("numberOfResidents", NumberOfResidents); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateRoadRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateRoadRequest.cs new file mode 100644 index 0000000000..151bb6cf5b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateRoadRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateRoadRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The lengthInMeters property + public double? LengthInMeters + { + get { return BackingStore?.Get("lengthInMeters"); } + set { BackingStore?.Set("lengthInMeters", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateRoadRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateRoadRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "lengthInMeters", n => { LengthInMeters = n.GetDoubleValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteDoubleValue("lengthInMeters", LengthInMeters); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateRoomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateRoomRequest.cs new file mode 100644 index 0000000000..3d0a9e66af --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateRoomRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateRoomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The surfaceInSquareMeters property + public int? SurfaceInSquareMeters + { + get { return BackingStore?.Get("surfaceInSquareMeters"); } + set { BackingStore?.Set("surfaceInSquareMeters", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateRoomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateRoomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "surfaceInSquareMeters", n => { SurfaceInSquareMeters = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("surfaceInSquareMeters", SurfaceInSquareMeters); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateStaffMemberRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateStaffMemberRequest.cs new file mode 100644 index 0000000000..c931b12b05 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateStaffMemberRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateStaffMemberRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateStaffMemberRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateStaffMemberRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateToiletRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateToiletRequest.cs new file mode 100644 index 0000000000..ce7a9e34f5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCreateToiletRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateToiletRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// The hasSink property + public bool? HasSink + { + get { return BackingStore?.Get("hasSink"); } + set { BackingStore?.Set("hasSink", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateToiletRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateToiletRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasSink", n => { HasSink = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasSink", HasSink); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCyclePathResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCyclePathResponse.cs new file mode 100644 index 0000000000..dd71a1b1db --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInCyclePathResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCyclePathResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInRoadResponse, IParsable + #pragma warning restore CS1591 + { + /// The hasLaneForPedestrians property + public bool? HasLaneForPedestrians + { + get { return BackingStore?.Get("hasLaneForPedestrians"); } + set { BackingStore?.Set("hasLaneForPedestrians", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCyclePathResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCyclePathResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasLaneForPedestrians", n => { HasLaneForPedestrians = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasLaneForPedestrians", HasLaneForPedestrians); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInDistrictResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInDistrictResponse.cs new file mode 100644 index 0000000000..edcee26109 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInDistrictResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInDistrictResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInDistrictResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInDistrictResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInFamilyHomeResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInFamilyHomeResponse.cs new file mode 100644 index 0000000000..47c1fb3b50 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInFamilyHomeResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInFamilyHomeResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInResidenceResponse, IParsable + #pragma warning restore CS1591 + { + /// The floorCount property + public int? FloorCount + { + get { return BackingStore?.Get("floorCount"); } + set { BackingStore?.Set("floorCount", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInFamilyHomeResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInFamilyHomeResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "floorCount", n => { FloorCount = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("floorCount", FloorCount); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInKitchenResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInKitchenResponse.cs new file mode 100644 index 0000000000..4dcf0cc6a5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInKitchenResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInKitchenResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// The hasPantry property + public bool? HasPantry + { + get { return BackingStore?.Get("hasPantry"); } + set { BackingStore?.Set("hasPantry", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInKitchenResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInKitchenResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasPantry", n => { HasPantry = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasPantry", HasPantry); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInLivingRoomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInLivingRoomResponse.cs new file mode 100644 index 0000000000..da11af8e85 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInLivingRoomResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInLivingRoomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// The hasDiningTable property + public bool? HasDiningTable + { + get { return BackingStore?.Get("hasDiningTable"); } + set { BackingStore?.Set("hasDiningTable", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInLivingRoomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInLivingRoomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasDiningTable", n => { HasDiningTable = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasDiningTable", HasDiningTable); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInMansionResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInMansionResponse.cs new file mode 100644 index 0000000000..a7f35ef114 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInMansionResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInMansionResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInResidenceResponse, IParsable + #pragma warning restore CS1591 + { + /// The ownerName property + public string? OwnerName + { + get { return BackingStore?.Get("ownerName"); } + set { BackingStore?.Set("ownerName", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInMansionResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInMansionResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "ownerName", n => { OwnerName = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("ownerName", OwnerName); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInResidenceResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInResidenceResponse.cs new file mode 100644 index 0000000000..071cb0e9ec --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInResidenceResponse.cs @@ -0,0 +1,65 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInResidenceResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInBuildingResponse, IParsable + #pragma warning restore CS1591 + { + /// The numberOfResidents property + public int? NumberOfResidents + { + get { return BackingStore?.Get("numberOfResidents"); } + set { BackingStore?.Set("numberOfResidents", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInResidenceResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInFamilyHomeResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInMansionResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInResidenceResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "numberOfResidents", n => { NumberOfResidents = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("numberOfResidents", NumberOfResidents); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInResponse.cs new file mode 100644 index 0000000000..5ac3043709 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInBathroomResponse(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInBedroomResponse(), + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInBuildingResponse(), + "cyclePaths" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCyclePathResponse(), + "districts" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInDistrictResponse(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInFamilyHomeResponse(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInKitchenResponse(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInLivingRoomResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInMansionResponse(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInResidenceResponse(), + "roads" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInRoadResponse(), + "rooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInRoomResponse(), + "staffMembers" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInStaffMemberResponse(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInToiletResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInRoadResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInRoadResponse.cs new file mode 100644 index 0000000000..353d2b3cac --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInRoadResponse.cs @@ -0,0 +1,64 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInRoadResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The lengthInMeters property + public double? LengthInMeters + { + get { return BackingStore?.Get("lengthInMeters"); } + set { BackingStore?.Set("lengthInMeters", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInRoadResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "cyclePaths" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCyclePathResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInRoadResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "lengthInMeters", n => { LengthInMeters = n.GetDoubleValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteDoubleValue("lengthInMeters", LengthInMeters); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInRoomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInRoomResponse.cs new file mode 100644 index 0000000000..29a8fe49b7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInRoomResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInRoomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The surfaceInSquareMeters property + public int? SurfaceInSquareMeters + { + get { return BackingStore?.Get("surfaceInSquareMeters"); } + set { BackingStore?.Set("surfaceInSquareMeters", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInRoomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInBathroomResponse(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInBedroomResponse(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInKitchenResponse(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInLivingRoomResponse(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInToiletResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInRoomResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "surfaceInSquareMeters", n => { SurfaceInSquareMeters = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("surfaceInSquareMeters", SurfaceInSquareMeters); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInStaffMemberResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInStaffMemberResponse.cs new file mode 100644 index 0000000000..3fe18d992a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInStaffMemberResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInStaffMemberResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInStaffMemberResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInStaffMemberResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInToiletResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInToiletResponse.cs new file mode 100644 index 0000000000..c754bda18d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInToiletResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInToiletResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// The hasSink property + public bool? HasSink + { + get { return BackingStore?.Get("hasSink"); } + set { BackingStore?.Set("hasSink", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInToiletResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInToiletResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasSink", n => { HasSink = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasSink", HasSink); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateBathroomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateBathroomRequest.cs new file mode 100644 index 0000000000..4d46869958 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateBathroomRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateBathroomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// The hasBath property + public bool? HasBath + { + get { return BackingStore?.Get("hasBath"); } + set { BackingStore?.Set("hasBath", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateBathroomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateBathroomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasBath", n => { HasBath = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasBath", HasBath); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateBedroomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateBedroomRequest.cs new file mode 100644 index 0000000000..c8534337f3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateBedroomRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateBedroomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// The bedCount property + public int? BedCount + { + get { return BackingStore?.Get("bedCount"); } + set { BackingStore?.Set("bedCount", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateBedroomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateBedroomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "bedCount", n => { BedCount = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("bedCount", BedCount); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateBuildingRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateBuildingRequest.cs new file mode 100644 index 0000000000..cbb1f2ce16 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateBuildingRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateBuildingRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The surfaceInSquareMeters property + public int? SurfaceInSquareMeters + { + get { return BackingStore?.Get("surfaceInSquareMeters"); } + set { BackingStore?.Set("surfaceInSquareMeters", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateBuildingRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateBuildingRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "surfaceInSquareMeters", n => { SurfaceInSquareMeters = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("surfaceInSquareMeters", SurfaceInSquareMeters); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateCyclePathRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateCyclePathRequest.cs new file mode 100644 index 0000000000..b12f5019e9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateCyclePathRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateCyclePathRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateRoadRequest, IParsable + #pragma warning restore CS1591 + { + /// The hasLaneForPedestrians property + public bool? HasLaneForPedestrians + { + get { return BackingStore?.Get("hasLaneForPedestrians"); } + set { BackingStore?.Set("hasLaneForPedestrians", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateCyclePathRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateCyclePathRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasLaneForPedestrians", n => { HasLaneForPedestrians = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasLaneForPedestrians", HasLaneForPedestrians); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateDistrictRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateDistrictRequest.cs new file mode 100644 index 0000000000..46b958d283 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateDistrictRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateDistrictRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateDistrictRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateDistrictRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateFamilyHomeRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateFamilyHomeRequest.cs new file mode 100644 index 0000000000..afb9ac9543 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateFamilyHomeRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateFamilyHomeRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// The floorCount property + public int? FloorCount + { + get { return BackingStore?.Get("floorCount"); } + set { BackingStore?.Set("floorCount", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateFamilyHomeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateFamilyHomeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "floorCount", n => { FloorCount = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("floorCount", FloorCount); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateKitchenRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateKitchenRequest.cs new file mode 100644 index 0000000000..0420a8da2e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateKitchenRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateKitchenRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// The hasPantry property + public bool? HasPantry + { + get { return BackingStore?.Get("hasPantry"); } + set { BackingStore?.Set("hasPantry", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateKitchenRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateKitchenRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasPantry", n => { HasPantry = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasPantry", HasPantry); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateLivingRoomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateLivingRoomRequest.cs new file mode 100644 index 0000000000..39140a4f6e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateLivingRoomRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateLivingRoomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// The hasDiningTable property + public bool? HasDiningTable + { + get { return BackingStore?.Get("hasDiningTable"); } + set { BackingStore?.Set("hasDiningTable", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateLivingRoomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateLivingRoomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasDiningTable", n => { HasDiningTable = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasDiningTable", HasDiningTable); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateMansionRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateMansionRequest.cs new file mode 100644 index 0000000000..50c0ba0f0b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateMansionRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateMansionRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// The ownerName property + public string? OwnerName + { + get { return BackingStore?.Get("ownerName"); } + set { BackingStore?.Set("ownerName", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateMansionRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateMansionRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "ownerName", n => { OwnerName = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("ownerName", OwnerName); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateRequest.cs new file mode 100644 index 0000000000..15c7d4374e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateRequest.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateBathroomRequest(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateBedroomRequest(), + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateBuildingRequest(), + "cyclePaths" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateCyclePathRequest(), + "districts" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateDistrictRequest(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateFamilyHomeRequest(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateKitchenRequest(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateLivingRoomRequest(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateMansionRequest(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateResidenceRequest(), + "roads" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateRoadRequest(), + "rooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateRoomRequest(), + "staffMembers" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateStaffMemberRequest(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateToiletRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateResidenceRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateResidenceRequest.cs new file mode 100644 index 0000000000..273f263669 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateResidenceRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateResidenceRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateBuildingRequest, IParsable + #pragma warning restore CS1591 + { + /// The numberOfResidents property + public int? NumberOfResidents + { + get { return BackingStore?.Get("numberOfResidents"); } + set { BackingStore?.Set("numberOfResidents", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateResidenceRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateResidenceRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "numberOfResidents", n => { NumberOfResidents = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("numberOfResidents", NumberOfResidents); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateRoadRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateRoadRequest.cs new file mode 100644 index 0000000000..a936222f15 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateRoadRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateRoadRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The lengthInMeters property + public double? LengthInMeters + { + get { return BackingStore?.Get("lengthInMeters"); } + set { BackingStore?.Set("lengthInMeters", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateRoadRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateRoadRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "lengthInMeters", n => { LengthInMeters = n.GetDoubleValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteDoubleValue("lengthInMeters", LengthInMeters); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateRoomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateRoomRequest.cs new file mode 100644 index 0000000000..3f22f9b402 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateRoomRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateRoomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The surfaceInSquareMeters property + public int? SurfaceInSquareMeters + { + get { return BackingStore?.Get("surfaceInSquareMeters"); } + set { BackingStore?.Set("surfaceInSquareMeters", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateRoomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateRoomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "surfaceInSquareMeters", n => { SurfaceInSquareMeters = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("surfaceInSquareMeters", SurfaceInSquareMeters); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateStaffMemberRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateStaffMemberRequest.cs new file mode 100644 index 0000000000..d378d79f6c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateStaffMemberRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateStaffMemberRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateStaffMemberRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateStaffMemberRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateToiletRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateToiletRequest.cs new file mode 100644 index 0000000000..97e23c3a87 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/AttributesInUpdateToiletRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateToiletRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// The hasSink property + public bool? HasSink + { + get { return BackingStore?.Get("hasSink"); } + set { BackingStore?.Set("hasSink", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateToiletRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateToiletRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasSink", n => { HasSink = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasSink", HasSink); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BathroomCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BathroomCollectionResponseDocument.cs new file mode 100644 index 0000000000..22ac6bbbb0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BathroomCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BathroomCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public BathroomCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BathroomCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BathroomCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInBathroomResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BathroomIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BathroomIdentifierInRequest.cs new file mode 100644 index 0000000000..aeeb9c4ec9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BathroomIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BathroomIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BathroomIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BathroomIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BathroomIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BathroomIdentifierInResponse.cs new file mode 100644 index 0000000000..b05115519b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BathroomIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BathroomIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BathroomIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BathroomIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BedroomCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BedroomCollectionResponseDocument.cs new file mode 100644 index 0000000000..a1b8258f5a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BedroomCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BedroomCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public BedroomCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BedroomCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BedroomCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInBedroomResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BedroomIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BedroomIdentifierInRequest.cs new file mode 100644 index 0000000000..26d6bdc060 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BedroomIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BedroomIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BedroomIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BedroomIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BedroomIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BedroomIdentifierInResponse.cs new file mode 100644 index 0000000000..e6084ade45 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BedroomIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BedroomIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BedroomIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BedroomIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BuildingCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BuildingCollectionResponseDocument.cs new file mode 100644 index 0000000000..de70d18e6c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BuildingCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BuildingCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public BuildingCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BuildingCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BuildingCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInBuildingResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BuildingIdentifierCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BuildingIdentifierCollectionResponseDocument.cs new file mode 100644 index 0000000000..94835279fc --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BuildingIdentifierCollectionResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BuildingIdentifierCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public BuildingIdentifierCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BuildingIdentifierCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BuildingIdentifierCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BuildingIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BuildingIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BuildingIdentifierInRequest.cs new file mode 100644 index 0000000000..4fd807029f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BuildingIdentifierInRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BuildingIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BuildingIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BuildingIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BuildingIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BuildingIdentifierInResponse.cs new file mode 100644 index 0000000000..9f6d930774 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BuildingIdentifierInResponse.cs @@ -0,0 +1,95 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BuildingIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BuildingResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public BuildingIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BuildingIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.FamilyHomeIdentifierInResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.MansionIdentifierInResponse(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierInResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BuildingIdentifierInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BuildingResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BuildingResourceType.cs new file mode 100644 index 0000000000..96359f1803 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/BuildingResourceType.cs @@ -0,0 +1,26 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum BuildingResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "familyHomes")] + #pragma warning disable CS1591 + FamilyHomes, + #pragma warning restore CS1591 + [EnumMember(Value = "mansions")] + #pragma warning disable CS1591 + Mansions, + #pragma warning restore CS1591 + [EnumMember(Value = "residences")] + #pragma warning disable CS1591 + Residences, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateBathroomRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateBathroomRequestDocument.cs new file mode 100644 index 0000000000..8cce0e4061 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateBathroomRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateBathroomRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateBathroomRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateBathroomRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateBathroomRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateBathroomRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateBathroomRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateBedroomRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateBedroomRequestDocument.cs new file mode 100644 index 0000000000..f413f2ce22 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateBedroomRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateBedroomRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateBedroomRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateBedroomRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateBedroomRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateBedroomRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateBedroomRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateBuildingRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateBuildingRequestDocument.cs new file mode 100644 index 0000000000..7976336947 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateBuildingRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateBuildingRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateBuildingRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateBuildingRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateBuildingRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateBuildingRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateBuildingRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateCyclePathRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateCyclePathRequestDocument.cs new file mode 100644 index 0000000000..efca2efb7f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateCyclePathRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateCyclePathRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateCyclePathRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateCyclePathRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateCyclePathRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateCyclePathRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateCyclePathRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateDistrictRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateDistrictRequestDocument.cs new file mode 100644 index 0000000000..d14a96477d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateDistrictRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateDistrictRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateDistrictRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateDistrictRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateDistrictRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateDistrictRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateDistrictRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateFamilyHomeRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateFamilyHomeRequestDocument.cs new file mode 100644 index 0000000000..d1856d8858 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateFamilyHomeRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateFamilyHomeRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateFamilyHomeRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateFamilyHomeRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateFamilyHomeRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateFamilyHomeRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateFamilyHomeRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateKitchenRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateKitchenRequestDocument.cs new file mode 100644 index 0000000000..cd810b9ba4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateKitchenRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateKitchenRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateKitchenRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateKitchenRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateKitchenRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateKitchenRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateKitchenRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateLivingRoomRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateLivingRoomRequestDocument.cs new file mode 100644 index 0000000000..f2299f2581 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateLivingRoomRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateLivingRoomRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateLivingRoomRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateLivingRoomRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateLivingRoomRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateLivingRoomRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateLivingRoomRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateMansionRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateMansionRequestDocument.cs new file mode 100644 index 0000000000..bb29334949 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateMansionRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateMansionRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateMansionRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateMansionRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateMansionRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateMansionRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateMansionRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateResidenceRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateResidenceRequestDocument.cs new file mode 100644 index 0000000000..7c58e8cb68 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateResidenceRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateResidenceRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateResidenceRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateResidenceRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateResidenceRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateResidenceRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateResidenceRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateRoadRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateRoadRequestDocument.cs new file mode 100644 index 0000000000..5e63e19af7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateRoadRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateRoadRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateRoadRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateRoadRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateRoadRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateRoadRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateRoadRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateRoomRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateRoomRequestDocument.cs new file mode 100644 index 0000000000..865ecfe4e1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateRoomRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateRoomRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateRoomRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateRoomRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateRoomRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateRoomRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateRoomRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateStaffMemberRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateStaffMemberRequestDocument.cs new file mode 100644 index 0000000000..2c1cbf0b3e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateStaffMemberRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateStaffMemberRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateStaffMemberRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateStaffMemberRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateStaffMemberRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateStaffMemberRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateStaffMemberRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateToiletRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateToiletRequestDocument.cs new file mode 100644 index 0000000000..f8cf45bef2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CreateToiletRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateToiletRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateToiletRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateToiletRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateToiletRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateToiletRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateToiletRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CyclePathCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CyclePathCollectionResponseDocument.cs new file mode 100644 index 0000000000..b0f928ca37 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CyclePathCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CyclePathCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CyclePathCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CyclePathCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CyclePathCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCyclePathResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CyclePathIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CyclePathIdentifierInRequest.cs new file mode 100644 index 0000000000..9bb5f6097b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CyclePathIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CyclePathIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoadIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CyclePathIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CyclePathIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CyclePathIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CyclePathIdentifierInResponse.cs new file mode 100644 index 0000000000..eeec76d0cf --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/CyclePathIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CyclePathIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoadIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CyclePathIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CyclePathIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInBathroomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInBathroomResponse.cs new file mode 100644 index 0000000000..3e623201a9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInBathroomResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInBathroomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInBathroomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInBathroomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInBedroomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInBedroomResponse.cs new file mode 100644 index 0000000000..d4fb16318a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInBedroomResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInBedroomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInBedroomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInBedroomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInBuildingResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInBuildingResponse.cs new file mode 100644 index 0000000000..cec5c7d131 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInBuildingResponse.cs @@ -0,0 +1,93 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInBuildingResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInBuildingResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInBuildingResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInBuildingResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInFamilyHomeResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInMansionResponse(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInResidenceResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInBuildingResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInBuildingResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInBuildingResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateBathroomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateBathroomRequest.cs new file mode 100644 index 0000000000..655cc0881a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateBathroomRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateBathroomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateBathroomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateBathroomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateBedroomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateBedroomRequest.cs new file mode 100644 index 0000000000..efb696ec11 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateBedroomRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateBedroomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateBedroomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateBedroomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateBuildingRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateBuildingRequest.cs new file mode 100644 index 0000000000..f0f2d916b4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateBuildingRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateBuildingRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateBuildingRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateBuildingRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateBuildingRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateBuildingRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateBuildingRequest.CreateFromDiscriminatorValue); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateBuildingRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateCyclePathRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateCyclePathRequest.cs new file mode 100644 index 0000000000..308bc4facb --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateCyclePathRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateCyclePathRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateRoadRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateCyclePathRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateCyclePathRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateDistrictRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateDistrictRequest.cs new file mode 100644 index 0000000000..77a20888c0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateDistrictRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateDistrictRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateDistrictRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateDistrictRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateDistrictRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateDistrictRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateDistrictRequest.CreateFromDiscriminatorValue); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateDistrictRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateFamilyHomeRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateFamilyHomeRequest.cs new file mode 100644 index 0000000000..edd88ebba0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateFamilyHomeRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateFamilyHomeRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateFamilyHomeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateFamilyHomeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateKitchenRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateKitchenRequest.cs new file mode 100644 index 0000000000..441eceef39 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateKitchenRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateKitchenRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateKitchenRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateKitchenRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateLivingRoomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateLivingRoomRequest.cs new file mode 100644 index 0000000000..6c65cfb4f3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateLivingRoomRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateLivingRoomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateLivingRoomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateLivingRoomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateMansionRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateMansionRequest.cs new file mode 100644 index 0000000000..07f8a426a0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateMansionRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateMansionRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateMansionRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateMansionRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateResidenceRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateResidenceRequest.cs new file mode 100644 index 0000000000..a58ad49e5b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateResidenceRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateResidenceRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateBuildingRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateResidenceRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateResidenceRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateRoadRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateRoadRequest.cs new file mode 100644 index 0000000000..37c37f4572 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateRoadRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateRoadRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateRoadRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateRoadRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateRoadRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateRoadRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateRoadRequest.CreateFromDiscriminatorValue); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateRoadRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateRoomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateRoomRequest.cs new file mode 100644 index 0000000000..3fd3ee76d8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateRoomRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateRoomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateRoomRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateRoomRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateRoomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateRoomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateRoomRequest.CreateFromDiscriminatorValue); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateRoomRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateStaffMemberRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateStaffMemberRequest.cs new file mode 100644 index 0000000000..8034b3e20d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateStaffMemberRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateStaffMemberRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateStaffMemberRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateStaffMemberRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateStaffMemberRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInCreateStaffMemberRequest.CreateFromDiscriminatorValue); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("lid", Lid); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateToiletRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateToiletRequest.cs new file mode 100644 index 0000000000..abcd4e2074 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCreateToiletRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateToiletRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateToiletRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateToiletRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCyclePathResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCyclePathResponse.cs new file mode 100644 index 0000000000..366e871404 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInCyclePathResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCyclePathResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInRoadResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCyclePathResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCyclePathResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInDistrictResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInDistrictResponse.cs new file mode 100644 index 0000000000..9379e911da --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInDistrictResponse.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInDistrictResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInDistrictResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInDistrictResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInDistrictResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInDistrictResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInDistrictResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetGuidValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInDistrictResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteGuidValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInFamilyHomeResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInFamilyHomeResponse.cs new file mode 100644 index 0000000000..4e6eee24ff --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInFamilyHomeResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInFamilyHomeResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInResidenceResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInFamilyHomeResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInFamilyHomeResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInKitchenResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInKitchenResponse.cs new file mode 100644 index 0000000000..f2f0ef9ac3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInKitchenResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInKitchenResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInKitchenResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInKitchenResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInLivingRoomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInLivingRoomResponse.cs new file mode 100644 index 0000000000..3f28800e7e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInLivingRoomResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInLivingRoomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInLivingRoomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInLivingRoomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInMansionResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInMansionResponse.cs new file mode 100644 index 0000000000..b729a9fde1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInMansionResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInMansionResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInResidenceResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInMansionResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInMansionResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInResidenceResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInResidenceResponse.cs new file mode 100644 index 0000000000..75f1ed93b9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInResidenceResponse.cs @@ -0,0 +1,56 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInResidenceResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInBuildingResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInResidenceResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInFamilyHomeResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInMansionResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInResidenceResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInRoadResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInRoadResponse.cs new file mode 100644 index 0000000000..e9fdc4ae57 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInRoadResponse.cs @@ -0,0 +1,91 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInRoadResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInRoadResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInRoadResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInRoadResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "cyclePaths" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCyclePathResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInRoadResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInRoadResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInRoadResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInRoomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInRoomResponse.cs new file mode 100644 index 0000000000..bcacceacf5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInRoomResponse.cs @@ -0,0 +1,95 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInRoomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInRoomResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInRoomResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInRoomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInBathroomResponse(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInBedroomResponse(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInKitchenResponse(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInLivingRoomResponse(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInToiletResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInRoomResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInRoomResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInRoomResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInStaffMemberResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInStaffMemberResponse.cs new file mode 100644 index 0000000000..0581fecac2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInStaffMemberResponse.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInStaffMemberResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInStaffMemberResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInStaffMemberResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInStaffMemberResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInStaffMemberResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInToiletResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInToiletResponse.cs new file mode 100644 index 0000000000..078ebec90c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInToiletResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInToiletResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInToiletResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInToiletResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateBathroomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateBathroomRequest.cs new file mode 100644 index 0000000000..1c21c30ada --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateBathroomRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateBathroomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateBathroomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateBathroomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateBedroomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateBedroomRequest.cs new file mode 100644 index 0000000000..100afbc623 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateBedroomRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateBedroomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateBedroomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateBedroomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateBuildingRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateBuildingRequest.cs new file mode 100644 index 0000000000..a665515864 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateBuildingRequest.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateBuildingRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateBuildingRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateBuildingRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateBuildingRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateBuildingRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateBuildingRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateBuildingRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateCyclePathRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateCyclePathRequest.cs new file mode 100644 index 0000000000..640b86b7d9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateCyclePathRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateCyclePathRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateRoadRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateCyclePathRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateCyclePathRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateDistrictRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateDistrictRequest.cs new file mode 100644 index 0000000000..6c0c9ae9fa --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateDistrictRequest.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateDistrictRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateDistrictRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateDistrictRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateDistrictRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateDistrictRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateDistrictRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetGuidValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateDistrictRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteGuidValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateFamilyHomeRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateFamilyHomeRequest.cs new file mode 100644 index 0000000000..0e72321271 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateFamilyHomeRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateFamilyHomeRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateFamilyHomeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateFamilyHomeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateKitchenRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateKitchenRequest.cs new file mode 100644 index 0000000000..8e8ecb22ff --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateKitchenRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateKitchenRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateKitchenRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateKitchenRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateLivingRoomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateLivingRoomRequest.cs new file mode 100644 index 0000000000..a01946a0ec --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateLivingRoomRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateLivingRoomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateLivingRoomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateLivingRoomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateMansionRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateMansionRequest.cs new file mode 100644 index 0000000000..963601d149 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateMansionRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateMansionRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateMansionRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateMansionRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateResidenceRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateResidenceRequest.cs new file mode 100644 index 0000000000..227dc7e5c1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateResidenceRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateResidenceRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateBuildingRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateResidenceRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateResidenceRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateRoadRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateRoadRequest.cs new file mode 100644 index 0000000000..dbdc255dd8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateRoadRequest.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateRoadRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateRoadRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateRoadRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateRoadRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateRoadRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateRoadRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateRoadRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateRoomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateRoomRequest.cs new file mode 100644 index 0000000000..6d768ab716 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateRoomRequest.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateRoomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateRoomRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateRoomRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateRoomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateRoomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateRoomRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateRoomRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateStaffMemberRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateStaffMemberRequest.cs new file mode 100644 index 0000000000..4244f65037 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateStaffMemberRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateStaffMemberRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateStaffMemberRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateStaffMemberRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateStaffMemberRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AttributesInUpdateStaffMemberRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateToiletRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateToiletRequest.cs new file mode 100644 index 0000000000..7525a6c1be --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DataInUpdateToiletRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateToiletRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateToiletRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateToiletRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DistrictCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DistrictCollectionResponseDocument.cs new file mode 100644 index 0000000000..7766139356 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/DistrictCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DistrictCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public DistrictCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DistrictCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DistrictCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInDistrictResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ErrorLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ErrorLinks.cs new file mode 100644 index 0000000000..d476e9cda8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ErrorLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// The about property + public string? About + { + get { return BackingStore?.Get("about"); } + set { BackingStore?.Set("about", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The type property + public string? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "about", n => { About = n.GetStringValue(); } }, + { "type", n => { Type = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("about", About); + writer.WriteStringValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ErrorObject.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ErrorObject.cs new file mode 100644 index 0000000000..5dd14b1cdd --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ErrorObject.cs @@ -0,0 +1,133 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorObject : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The code property + public string? Code + { + get { return BackingStore?.Get("code"); } + set { BackingStore?.Set("code", value); } + } + + /// The detail property + public string? Detail + { + get { return BackingStore?.Get("detail"); } + set { BackingStore?.Set("detail", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The source property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorSource? Source + { + get { return BackingStore?.Get("source"); } + set { BackingStore?.Set("source", value); } + } + + /// The status property + public string? Status + { + get { return BackingStore?.Get("status"); } + set { BackingStore?.Set("status", value); } + } + + /// The title property + public string? Title + { + get { return BackingStore?.Get("title"); } + set { BackingStore?.Set("title", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorObject() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorObject CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorObject(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "code", n => { Code = n.GetStringValue(); } }, + { "detail", n => { Detail = n.GetStringValue(); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "source", n => { Source = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorSource.CreateFromDiscriminatorValue); } }, + { "status", n => { Status = n.GetStringValue(); } }, + { "title", n => { Title = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("code", Code); + writer.WriteStringValue("detail", Detail); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + writer.WriteObjectValue("source", Source); + writer.WriteStringValue("status", Status); + writer.WriteStringValue("title", Title); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ErrorResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ErrorResponseDocument.cs new file mode 100644 index 0000000000..ac5ec03ee8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ErrorResponseDocument.cs @@ -0,0 +1,92 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorResponseDocument : ApiException, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The errors property + public List? Errors + { + get { return BackingStore?.Get?>("errors"); } + set { BackingStore?.Set("errors", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The primary error message. + public override string Message { get => base.Message; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "errors", n => { Errors = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorObject.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("errors", Errors); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ErrorSource.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ErrorSource.cs new file mode 100644 index 0000000000..3bac05fc46 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ErrorSource.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorSource : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The header property + public string? Header + { + get { return BackingStore?.Get("header"); } + set { BackingStore?.Set("header", value); } + } + + /// The parameter property + public string? Parameter + { + get { return BackingStore?.Get("parameter"); } + set { BackingStore?.Set("parameter", value); } + } + + /// The pointer property + public string? Pointer + { + get { return BackingStore?.Get("pointer"); } + set { BackingStore?.Set("pointer", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorSource() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorSource CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorSource(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "header", n => { Header = n.GetStringValue(); } }, + { "parameter", n => { Parameter = n.GetStringValue(); } }, + { "pointer", n => { Pointer = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("header", Header); + writer.WriteStringValue("parameter", Parameter); + writer.WriteStringValue("pointer", Pointer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ErrorTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ErrorTopLevelLinks.cs new file mode 100644 index 0000000000..0e310de4e0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ErrorTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/FamilyHomeCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/FamilyHomeCollectionResponseDocument.cs new file mode 100644 index 0000000000..6b2bf04584 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/FamilyHomeCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class FamilyHomeCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public FamilyHomeCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.FamilyHomeCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.FamilyHomeCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInFamilyHomeResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/FamilyHomeIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/FamilyHomeIdentifierInRequest.cs new file mode 100644 index 0000000000..e0b5fc07e5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/FamilyHomeIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class FamilyHomeIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.FamilyHomeIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.FamilyHomeIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/FamilyHomeIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/FamilyHomeIdentifierInResponse.cs new file mode 100644 index 0000000000..ba86f418d6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/FamilyHomeIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class FamilyHomeIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.FamilyHomeIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.FamilyHomeIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/IdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/IdentifierInRequest.cs new file mode 100644 index 0000000000..1fdd61d52f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/IdentifierInRequest.cs @@ -0,0 +1,96 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class IdentifierInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public IdentifierInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.IdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BathroomIdentifierInRequest(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BedroomIdentifierInRequest(), + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BuildingIdentifierInRequest(), + "cyclePaths" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CyclePathIdentifierInRequest(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.FamilyHomeIdentifierInRequest(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.KitchenIdentifierInRequest(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.LivingRoomIdentifierInRequest(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.MansionIdentifierInRequest(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierInRequest(), + "roads" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoadIdentifierInRequest(), + "rooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomIdentifierInRequest(), + "staffMembers" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.StaffMemberIdentifierInRequest(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToiletIdentifierInRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.IdentifierInRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/KitchenCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/KitchenCollectionResponseDocument.cs new file mode 100644 index 0000000000..1380ce2f96 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/KitchenCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class KitchenCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public KitchenCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.KitchenCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.KitchenCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInKitchenResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/KitchenIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/KitchenIdentifierInRequest.cs new file mode 100644 index 0000000000..f1da5bb35a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/KitchenIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class KitchenIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.KitchenIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.KitchenIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/KitchenIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/KitchenIdentifierInResponse.cs new file mode 100644 index 0000000000..ba4007e42f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/KitchenIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class KitchenIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.KitchenIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.KitchenIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/LivingRoomCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/LivingRoomCollectionResponseDocument.cs new file mode 100644 index 0000000000..701925f556 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/LivingRoomCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class LivingRoomCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public LivingRoomCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.LivingRoomCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.LivingRoomCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInLivingRoomResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/LivingRoomIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/LivingRoomIdentifierInRequest.cs new file mode 100644 index 0000000000..4f89cfa7fa --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/LivingRoomIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class LivingRoomIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.LivingRoomIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.LivingRoomIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/LivingRoomIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/LivingRoomIdentifierInResponse.cs new file mode 100644 index 0000000000..6cadc432df --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/LivingRoomIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class LivingRoomIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.LivingRoomIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.LivingRoomIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/MansionCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/MansionCollectionResponseDocument.cs new file mode 100644 index 0000000000..eb8354866f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/MansionCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class MansionCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public MansionCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.MansionCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.MansionCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInMansionResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/MansionIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/MansionIdentifierInRequest.cs new file mode 100644 index 0000000000..d538d1b9d7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/MansionIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class MansionIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.MansionIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.MansionIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/MansionIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/MansionIdentifierInResponse.cs new file mode 100644 index 0000000000..6b68d36a0e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/MansionIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class MansionIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.MansionIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.MansionIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/Meta.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/Meta.cs new file mode 100644 index 0000000000..0f74d52b58 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/Meta.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class Meta : IAdditionalDataHolder, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + public IDictionary AdditionalData + { + get { return BackingStore.Get>("AdditionalData") ?? new Dictionary(); } + set { BackingStore.Set("AdditionalData", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// + /// Instantiates a new and sets the default values. + /// + public Meta() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + AdditionalData = new Dictionary(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteAdditionalData(AdditionalData); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/OperationsRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/OperationsRequestDocument.cs new file mode 100644 index 0000000000..4f0d8343cd --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/OperationsRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class OperationsRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// The atomicOperations property + public List? AtomicOperations + { + get { return BackingStore?.Get?>("atomic:operations"); } + set { BackingStore?.Set("atomic:operations", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public OperationsRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.OperationsRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.OperationsRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "atomic:operations", n => { AtomicOperations = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AtomicOperation.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("atomic:operations", AtomicOperations); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/OperationsResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/OperationsResponseDocument.cs new file mode 100644 index 0000000000..16ea89097e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/OperationsResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class OperationsResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// The atomicResults property + public List? AtomicResults + { + get { return BackingStore?.Get?>("atomic:results"); } + set { BackingStore?.Set("atomic:results", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public OperationsResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.OperationsResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.OperationsResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "atomic:results", n => { AtomicResults = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.AtomicResult.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("atomic:results", AtomicResults); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryBathroomResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryBathroomResponseDocument.cs new file mode 100644 index 0000000000..0a53bb41b2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryBathroomResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryBathroomResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInBathroomResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryBathroomResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryBathroomResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryBathroomResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInBathroomResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryBedroomResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryBedroomResponseDocument.cs new file mode 100644 index 0000000000..047a550dc9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryBedroomResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryBedroomResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInBedroomResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryBedroomResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryBedroomResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryBedroomResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInBedroomResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryBuildingResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryBuildingResponseDocument.cs new file mode 100644 index 0000000000..229e7cab38 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryBuildingResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryBuildingResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInBuildingResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryBuildingResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryBuildingResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryBuildingResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInBuildingResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryCyclePathResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryCyclePathResponseDocument.cs new file mode 100644 index 0000000000..af051ea917 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryCyclePathResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryCyclePathResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCyclePathResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryCyclePathResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryCyclePathResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryCyclePathResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCyclePathResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryDistrictResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryDistrictResponseDocument.cs new file mode 100644 index 0000000000..5dca10e598 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryDistrictResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryDistrictResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInDistrictResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryDistrictResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryDistrictResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryDistrictResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInDistrictResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryFamilyHomeResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryFamilyHomeResponseDocument.cs new file mode 100644 index 0000000000..99e139e5d3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryFamilyHomeResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryFamilyHomeResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInFamilyHomeResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryFamilyHomeResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryFamilyHomeResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryFamilyHomeResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInFamilyHomeResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryKitchenResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryKitchenResponseDocument.cs new file mode 100644 index 0000000000..e99ce77690 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryKitchenResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryKitchenResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInKitchenResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryKitchenResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryKitchenResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryKitchenResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInKitchenResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryLivingRoomResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryLivingRoomResponseDocument.cs new file mode 100644 index 0000000000..f125e86438 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryLivingRoomResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryLivingRoomResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInLivingRoomResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryLivingRoomResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryLivingRoomResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryLivingRoomResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInLivingRoomResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryMansionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryMansionResponseDocument.cs new file mode 100644 index 0000000000..e9a202c5f5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryMansionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryMansionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInMansionResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryMansionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryMansionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryMansionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInMansionResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryResidenceResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryResidenceResponseDocument.cs new file mode 100644 index 0000000000..0fb5f7ad71 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryResidenceResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryResidenceResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInResidenceResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryResidenceResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryResidenceResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryResidenceResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInResidenceResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryRoadResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryRoadResponseDocument.cs new file mode 100644 index 0000000000..b2bf2db1d6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryRoadResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryRoadResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInRoadResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryRoadResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryRoadResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryRoadResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInRoadResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryRoomResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryRoomResponseDocument.cs new file mode 100644 index 0000000000..82def113ea --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryRoomResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryRoomResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInRoomResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryRoomResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryRoomResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryRoomResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInRoomResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryStaffMemberResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryStaffMemberResponseDocument.cs new file mode 100644 index 0000000000..f841d26997 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryStaffMemberResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryStaffMemberResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInStaffMemberResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryStaffMemberResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryStaffMemberResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryStaffMemberResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInStaffMemberResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryToiletResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryToiletResponseDocument.cs new file mode 100644 index 0000000000..c67dbdc7d6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/PrimaryToiletResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryToiletResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInToiletResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryToiletResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryToiletResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryToiletResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInToiletResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipLinks.cs new file mode 100644 index 0000000000..edb075fccd --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInBathroomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInBathroomResponse.cs new file mode 100644 index 0000000000..8352aee801 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInBathroomResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInBathroomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInBathroomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInBathroomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInBedroomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInBedroomResponse.cs new file mode 100644 index 0000000000..91574b4c30 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInBedroomResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInBedroomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInBedroomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInBedroomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInBuildingResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInBuildingResponse.cs new file mode 100644 index 0000000000..cf37d2ec1b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInBuildingResponse.cs @@ -0,0 +1,57 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInBuildingResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInBuildingResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInFamilyHomeResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInMansionResponse(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInResidenceResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInBuildingResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateBathroomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateBathroomRequest.cs new file mode 100644 index 0000000000..737a5b70f8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateBathroomRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateBathroomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateBathroomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateBathroomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateBedroomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateBedroomRequest.cs new file mode 100644 index 0000000000..4419001c73 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateBedroomRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateBedroomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateBedroomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateBedroomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateBuildingRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateBuildingRequest.cs new file mode 100644 index 0000000000..e79429baef --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateBuildingRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateBuildingRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateBuildingRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateBuildingRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateCyclePathRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateCyclePathRequest.cs new file mode 100644 index 0000000000..5ac47d4ef0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateCyclePathRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateCyclePathRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateRoadRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateCyclePathRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateCyclePathRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateDistrictRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateDistrictRequest.cs new file mode 100644 index 0000000000..f69df43062 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateDistrictRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateDistrictRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The buildings property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyBuildingInRequest? Buildings + { + get { return BackingStore?.Get("buildings"); } + set { BackingStore?.Set("buildings", value); } + } + + /// The roads property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoadInRequest? Roads + { + get { return BackingStore?.Get("roads"); } + set { BackingStore?.Set("roads", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateDistrictRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateDistrictRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "buildings", n => { Buildings = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyBuildingInRequest.CreateFromDiscriminatorValue); } }, + { "roads", n => { Roads = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoadInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("buildings", Buildings); + writer.WriteObjectValue("roads", Roads); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateFamilyHomeRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateFamilyHomeRequest.cs new file mode 100644 index 0000000000..80e5e94f80 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateFamilyHomeRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateFamilyHomeRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateFamilyHomeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateFamilyHomeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateKitchenRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateKitchenRequest.cs new file mode 100644 index 0000000000..184853c913 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateKitchenRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateKitchenRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateKitchenRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateKitchenRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateLivingRoomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateLivingRoomRequest.cs new file mode 100644 index 0000000000..36c8ec0bf2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateLivingRoomRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateLivingRoomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateLivingRoomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateLivingRoomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateMansionRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateMansionRequest.cs new file mode 100644 index 0000000000..8c59f6a798 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateMansionRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateMansionRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// The staff property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyStaffMemberInRequest? Staff + { + get { return BackingStore?.Get("staff"); } + set { BackingStore?.Set("staff", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateMansionRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateMansionRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "staff", n => { Staff = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyStaffMemberInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("staff", Staff); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateRequest.cs new file mode 100644 index 0000000000..a95af47983 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateRequest.cs @@ -0,0 +1,87 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateBathroomRequest(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateBedroomRequest(), + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateBuildingRequest(), + "cyclePaths" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateCyclePathRequest(), + "districts" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateDistrictRequest(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateFamilyHomeRequest(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateKitchenRequest(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateLivingRoomRequest(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateMansionRequest(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateResidenceRequest(), + "roads" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateRoadRequest(), + "rooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateRoomRequest(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateToiletRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateResidenceRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateResidenceRequest.cs new file mode 100644 index 0000000000..c97a7af201 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateResidenceRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateResidenceRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateBuildingRequest, IParsable + #pragma warning restore CS1591 + { + /// The rooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest? Rooms + { + get { return BackingStore?.Get("rooms"); } + set { BackingStore?.Set("rooms", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateResidenceRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateResidenceRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "rooms", n => { Rooms = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("rooms", Rooms); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateRoadRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateRoadRequest.cs new file mode 100644 index 0000000000..e57864b7da --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateRoadRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateRoadRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateRoadRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateRoadRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateRoomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateRoomRequest.cs new file mode 100644 index 0000000000..cb5fba02f9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateRoomRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateRoomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToOneResidenceInRequest? Residence + { + get { return BackingStore?.Get("residence"); } + set { BackingStore?.Set("residence", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateRoomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateRoomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "residence", n => { Residence = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToOneResidenceInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("residence", Residence); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateToiletRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateToiletRequest.cs new file mode 100644 index 0000000000..f0e53f3077 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCreateToiletRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateToiletRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateToiletRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCreateToiletRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCyclePathResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCyclePathResponse.cs new file mode 100644 index 0000000000..09ab4df065 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInCyclePathResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCyclePathResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInRoadResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCyclePathResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCyclePathResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInDistrictResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInDistrictResponse.cs new file mode 100644 index 0000000000..dc60b22687 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInDistrictResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInDistrictResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// The buildings property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyBuildingInResponse? Buildings + { + get { return BackingStore?.Get("buildings"); } + set { BackingStore?.Set("buildings", value); } + } + + /// The roads property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoadInResponse? Roads + { + get { return BackingStore?.Get("roads"); } + set { BackingStore?.Set("roads", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInDistrictResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInDistrictResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "buildings", n => { Buildings = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyBuildingInResponse.CreateFromDiscriminatorValue); } }, + { "roads", n => { Roads = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoadInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("buildings", Buildings); + writer.WriteObjectValue("roads", Roads); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInFamilyHomeResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInFamilyHomeResponse.cs new file mode 100644 index 0000000000..a879fb7031 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInFamilyHomeResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInFamilyHomeResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInResidenceResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInFamilyHomeResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInFamilyHomeResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInKitchenResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInKitchenResponse.cs new file mode 100644 index 0000000000..98398c4035 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInKitchenResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInKitchenResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInKitchenResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInKitchenResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInLivingRoomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInLivingRoomResponse.cs new file mode 100644 index 0000000000..9655f86fb6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInLivingRoomResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInLivingRoomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInLivingRoomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInLivingRoomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInMansionResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInMansionResponse.cs new file mode 100644 index 0000000000..fcd806b8d1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInMansionResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInMansionResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInResidenceResponse, IParsable + #pragma warning restore CS1591 + { + /// The staff property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyStaffMemberInResponse? Staff + { + get { return BackingStore?.Get("staff"); } + set { BackingStore?.Set("staff", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInMansionResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInMansionResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "staff", n => { Staff = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyStaffMemberInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("staff", Staff); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInResidenceResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInResidenceResponse.cs new file mode 100644 index 0000000000..cb46857698 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInResidenceResponse.cs @@ -0,0 +1,65 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInResidenceResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInBuildingResponse, IParsable + #pragma warning restore CS1591 + { + /// The rooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInResponse? Rooms + { + get { return BackingStore?.Get("rooms"); } + set { BackingStore?.Set("rooms", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInResidenceResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInFamilyHomeResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInMansionResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInResidenceResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "rooms", n => { Rooms = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("rooms", Rooms); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInResponse.cs new file mode 100644 index 0000000000..94c2c64322 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInResponse.cs @@ -0,0 +1,87 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInBathroomResponse(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInBedroomResponse(), + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInBuildingResponse(), + "cyclePaths" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCyclePathResponse(), + "districts" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInDistrictResponse(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInFamilyHomeResponse(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInKitchenResponse(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInLivingRoomResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInMansionResponse(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInResidenceResponse(), + "roads" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInRoadResponse(), + "rooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInRoomResponse(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInToiletResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInRoadResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInRoadResponse.cs new file mode 100644 index 0000000000..67d482e841 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInRoadResponse.cs @@ -0,0 +1,55 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInRoadResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInRoadResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "cyclePaths" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInCyclePathResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInRoadResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInRoomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInRoomResponse.cs new file mode 100644 index 0000000000..9cde803fb7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInRoomResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInRoomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToOneResidenceInResponse? Residence + { + get { return BackingStore?.Get("residence"); } + set { BackingStore?.Set("residence", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInRoomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInBathroomResponse(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInBedroomResponse(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInKitchenResponse(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInLivingRoomResponse(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInToiletResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInRoomResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "residence", n => { Residence = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToOneResidenceInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("residence", Residence); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInToiletResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInToiletResponse.cs new file mode 100644 index 0000000000..c4d5ceaa2f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInToiletResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInToiletResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInToiletResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInToiletResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateBathroomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateBathroomRequest.cs new file mode 100644 index 0000000000..aab9b0b08c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateBathroomRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateBathroomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateBathroomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateBathroomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateBedroomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateBedroomRequest.cs new file mode 100644 index 0000000000..1e6b84cb27 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateBedroomRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateBedroomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateBedroomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateBedroomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateBuildingRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateBuildingRequest.cs new file mode 100644 index 0000000000..e88c23c337 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateBuildingRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateBuildingRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateBuildingRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateBuildingRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateCyclePathRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateCyclePathRequest.cs new file mode 100644 index 0000000000..259d5aacfc --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateCyclePathRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateCyclePathRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateRoadRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateCyclePathRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateCyclePathRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateDistrictRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateDistrictRequest.cs new file mode 100644 index 0000000000..1eed06645d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateDistrictRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateDistrictRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The buildings property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyBuildingInRequest? Buildings + { + get { return BackingStore?.Get("buildings"); } + set { BackingStore?.Set("buildings", value); } + } + + /// The roads property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoadInRequest? Roads + { + get { return BackingStore?.Get("roads"); } + set { BackingStore?.Set("roads", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateDistrictRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateDistrictRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "buildings", n => { Buildings = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyBuildingInRequest.CreateFromDiscriminatorValue); } }, + { "roads", n => { Roads = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoadInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("buildings", Buildings); + writer.WriteObjectValue("roads", Roads); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateFamilyHomeRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateFamilyHomeRequest.cs new file mode 100644 index 0000000000..f480dcbdbd --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateFamilyHomeRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateFamilyHomeRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateFamilyHomeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateFamilyHomeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateKitchenRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateKitchenRequest.cs new file mode 100644 index 0000000000..d48b9e70ea --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateKitchenRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateKitchenRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateKitchenRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateKitchenRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateLivingRoomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateLivingRoomRequest.cs new file mode 100644 index 0000000000..f63f0c619f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateLivingRoomRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateLivingRoomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateLivingRoomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateLivingRoomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateMansionRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateMansionRequest.cs new file mode 100644 index 0000000000..7e8a5f52ee --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateMansionRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateMansionRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// The staff property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyStaffMemberInRequest? Staff + { + get { return BackingStore?.Get("staff"); } + set { BackingStore?.Set("staff", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateMansionRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateMansionRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "staff", n => { Staff = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyStaffMemberInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("staff", Staff); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateRequest.cs new file mode 100644 index 0000000000..1f9bdce3dc --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateRequest.cs @@ -0,0 +1,87 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateBathroomRequest(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateBedroomRequest(), + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateBuildingRequest(), + "cyclePaths" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateCyclePathRequest(), + "districts" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateDistrictRequest(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateFamilyHomeRequest(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateKitchenRequest(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateLivingRoomRequest(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateMansionRequest(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateResidenceRequest(), + "roads" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateRoadRequest(), + "rooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateRoomRequest(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateToiletRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateResidenceRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateResidenceRequest.cs new file mode 100644 index 0000000000..e9b4cc7a4d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateResidenceRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateResidenceRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateBuildingRequest, IParsable + #pragma warning restore CS1591 + { + /// The rooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest? Rooms + { + get { return BackingStore?.Get("rooms"); } + set { BackingStore?.Set("rooms", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateResidenceRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateResidenceRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "rooms", n => { Rooms = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("rooms", Rooms); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateRoadRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateRoadRequest.cs new file mode 100644 index 0000000000..143c62ec6f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateRoadRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateRoadRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateRoadRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateRoadRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateRoomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateRoomRequest.cs new file mode 100644 index 0000000000..2e3173d1fe --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateRoomRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateRoomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToOneResidenceInRequest? Residence + { + get { return BackingStore?.Get("residence"); } + set { BackingStore?.Set("residence", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateRoomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateRoomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "residence", n => { Residence = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToOneResidenceInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("residence", Residence); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateToiletRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateToiletRequest.cs new file mode 100644 index 0000000000..80c56ae480 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RelationshipsInUpdateToiletRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateToiletRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateToiletRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipsInUpdateToiletRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResidenceCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResidenceCollectionResponseDocument.cs new file mode 100644 index 0000000000..8cb16dfb26 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResidenceCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResidenceCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResidenceCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInResidenceResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResidenceIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResidenceIdentifierInRequest.cs new file mode 100644 index 0000000000..b0bdf82a9f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResidenceIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResidenceIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BuildingIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResidenceIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResidenceIdentifierInResponse.cs new file mode 100644 index 0000000000..2d7d1bac29 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResidenceIdentifierInResponse.cs @@ -0,0 +1,56 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResidenceIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BuildingIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.FamilyHomeIdentifierInResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.MansionIdentifierInResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResidenceIdentifierResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResidenceIdentifierResponseDocument.cs new file mode 100644 index 0000000000..5e85183b85 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResidenceIdentifierResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResidenceIdentifierResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceIdentifierTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResidenceIdentifierResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceIdentifierTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceCollectionTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceCollectionTopLevelLinks.cs new file mode 100644 index 0000000000..1f06ec35c7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceCollectionTopLevelLinks.cs @@ -0,0 +1,115 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceCollectionTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The first property + public string? First + { + get { return BackingStore?.Get("first"); } + set { BackingStore?.Set("first", value); } + } + + /// The last property + public string? Last + { + get { return BackingStore?.Get("last"); } + set { BackingStore?.Set("last", value); } + } + + /// The next property + public string? Next + { + get { return BackingStore?.Get("next"); } + set { BackingStore?.Set("next", value); } + } + + /// The prev property + public string? Prev + { + get { return BackingStore?.Get("prev"); } + set { BackingStore?.Set("prev", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceCollectionTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "first", n => { First = n.GetStringValue(); } }, + { "last", n => { Last = n.GetStringValue(); } }, + { "next", n => { Next = n.GetStringValue(); } }, + { "prev", n => { Prev = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("first", First); + writer.WriteStringValue("last", Last); + writer.WriteStringValue("next", Next); + writer.WriteStringValue("prev", Prev); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs new file mode 100644 index 0000000000..170ee686d4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs @@ -0,0 +1,124 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceIdentifierCollectionTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The first property + public string? First + { + get { return BackingStore?.Get("first"); } + set { BackingStore?.Set("first", value); } + } + + /// The last property + public string? Last + { + get { return BackingStore?.Get("last"); } + set { BackingStore?.Set("last", value); } + } + + /// The next property + public string? Next + { + get { return BackingStore?.Get("next"); } + set { BackingStore?.Set("next", value); } + } + + /// The prev property + public string? Prev + { + get { return BackingStore?.Get("prev"); } + set { BackingStore?.Set("prev", value); } + } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceIdentifierCollectionTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "first", n => { First = n.GetStringValue(); } }, + { "last", n => { Last = n.GetStringValue(); } }, + { "next", n => { Next = n.GetStringValue(); } }, + { "prev", n => { Prev = n.GetStringValue(); } }, + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("first", First); + writer.WriteStringValue("last", Last); + writer.WriteStringValue("next", Next); + writer.WriteStringValue("prev", Prev); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceIdentifierTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceIdentifierTopLevelLinks.cs new file mode 100644 index 0000000000..2e16fdce5a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceIdentifierTopLevelLinks.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceIdentifierTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceIdentifierTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceIdentifierTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceIdentifierTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceInCreateRequest.cs new file mode 100644 index 0000000000..34d11a9811 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceInCreateRequest.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateBathroomRequest(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateBedroomRequest(), + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateBuildingRequest(), + "cyclePaths" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateCyclePathRequest(), + "districts" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateDistrictRequest(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateFamilyHomeRequest(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateKitchenRequest(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateLivingRoomRequest(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateMansionRequest(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateResidenceRequest(), + "roads" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateRoadRequest(), + "rooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateRoomRequest(), + "staffMembers" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateStaffMemberRequest(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCreateToiletRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceInResponse.cs new file mode 100644 index 0000000000..89478f5840 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceInResponse.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInBathroomResponse(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInBedroomResponse(), + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInBuildingResponse(), + "cyclePaths" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInCyclePathResponse(), + "districts" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInDistrictResponse(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInFamilyHomeResponse(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInKitchenResponse(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInLivingRoomResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInMansionResponse(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInResidenceResponse(), + "roads" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInRoadResponse(), + "rooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInRoomResponse(), + "staffMembers" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInStaffMemberResponse(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInToiletResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceInUpdateRequest.cs new file mode 100644 index 0000000000..05536ed7be --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceInUpdateRequest.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateBathroomRequest(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateBedroomRequest(), + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateBuildingRequest(), + "cyclePaths" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateCyclePathRequest(), + "districts" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateDistrictRequest(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateFamilyHomeRequest(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateKitchenRequest(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateLivingRoomRequest(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateMansionRequest(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateResidenceRequest(), + "roads" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateRoadRequest(), + "rooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateRoomRequest(), + "staffMembers" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateStaffMemberRequest(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateToiletRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceLinks.cs new file mode 100644 index 0000000000..d0c613c121 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceLinks.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceTopLevelLinks.cs new file mode 100644 index 0000000000..c0cd803664 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceType.cs new file mode 100644 index 0000000000..069b5a875b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ResourceType.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum ResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "bathrooms")] + #pragma warning disable CS1591 + Bathrooms, + #pragma warning restore CS1591 + [EnumMember(Value = "bedrooms")] + #pragma warning disable CS1591 + Bedrooms, + #pragma warning restore CS1591 + [EnumMember(Value = "buildings")] + #pragma warning disable CS1591 + Buildings, + #pragma warning restore CS1591 + [EnumMember(Value = "cyclePaths")] + #pragma warning disable CS1591 + CyclePaths, + #pragma warning restore CS1591 + [EnumMember(Value = "districts")] + #pragma warning disable CS1591 + Districts, + #pragma warning restore CS1591 + [EnumMember(Value = "familyHomes")] + #pragma warning disable CS1591 + FamilyHomes, + #pragma warning restore CS1591 + [EnumMember(Value = "kitchens")] + #pragma warning disable CS1591 + Kitchens, + #pragma warning restore CS1591 + [EnumMember(Value = "livingRooms")] + #pragma warning disable CS1591 + LivingRooms, + #pragma warning restore CS1591 + [EnumMember(Value = "mansions")] + #pragma warning disable CS1591 + Mansions, + #pragma warning restore CS1591 + [EnumMember(Value = "residences")] + #pragma warning disable CS1591 + Residences, + #pragma warning restore CS1591 + [EnumMember(Value = "roads")] + #pragma warning disable CS1591 + Roads, + #pragma warning restore CS1591 + [EnumMember(Value = "rooms")] + #pragma warning disable CS1591 + Rooms, + #pragma warning restore CS1591 + [EnumMember(Value = "staffMembers")] + #pragma warning disable CS1591 + StaffMembers, + #pragma warning restore CS1591 + [EnumMember(Value = "toilets")] + #pragma warning disable CS1591 + Toilets, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoadCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoadCollectionResponseDocument.cs new file mode 100644 index 0000000000..bd41c2a83f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoadCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RoadCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RoadCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoadCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoadCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInRoadResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoadIdentifierCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoadIdentifierCollectionResponseDocument.cs new file mode 100644 index 0000000000..13c9b3b1b3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoadIdentifierCollectionResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RoadIdentifierCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RoadIdentifierCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoadIdentifierCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoadIdentifierCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoadIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoadIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoadIdentifierInRequest.cs new file mode 100644 index 0000000000..221e23a4fa --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoadIdentifierInRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RoadIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoadIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoadIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoadIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoadIdentifierInResponse.cs new file mode 100644 index 0000000000..439d90b774 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoadIdentifierInResponse.cs @@ -0,0 +1,93 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RoadIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoadResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RoadIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoadIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "cyclePaths" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CyclePathIdentifierInResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoadIdentifierInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoadResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoadResourceType.cs new file mode 100644 index 0000000000..7ff194472c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoadResourceType.cs @@ -0,0 +1,22 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum RoadResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "cyclePaths")] + #pragma warning disable CS1591 + CyclePaths, + #pragma warning restore CS1591 + [EnumMember(Value = "roads")] + #pragma warning disable CS1591 + Roads, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoomCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoomCollectionResponseDocument.cs new file mode 100644 index 0000000000..aab3e24817 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoomCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RoomCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RoomCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInRoomResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoomIdentifierCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoomIdentifierCollectionResponseDocument.cs new file mode 100644 index 0000000000..8db59f0d81 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoomIdentifierCollectionResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RoomIdentifierCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RoomIdentifierCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomIdentifierCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomIdentifierCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoomIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoomIdentifierInRequest.cs new file mode 100644 index 0000000000..35d91313ad --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoomIdentifierInRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RoomIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoomIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoomIdentifierInResponse.cs new file mode 100644 index 0000000000..bd2edf44f5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoomIdentifierInResponse.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RoomIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RoomIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BathroomIdentifierInResponse(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BedroomIdentifierInResponse(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.KitchenIdentifierInResponse(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.LivingRoomIdentifierInResponse(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToiletIdentifierInResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomIdentifierInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoomResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoomResourceType.cs new file mode 100644 index 0000000000..3b43c0ea15 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/RoomResourceType.cs @@ -0,0 +1,34 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum RoomResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "bathrooms")] + #pragma warning disable CS1591 + Bathrooms, + #pragma warning restore CS1591 + [EnumMember(Value = "bedrooms")] + #pragma warning disable CS1591 + Bedrooms, + #pragma warning restore CS1591 + [EnumMember(Value = "kitchens")] + #pragma warning disable CS1591 + Kitchens, + #pragma warning restore CS1591 + [EnumMember(Value = "livingRooms")] + #pragma warning disable CS1591 + LivingRooms, + #pragma warning restore CS1591 + [EnumMember(Value = "toilets")] + #pragma warning disable CS1591 + Toilets, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/SecondaryResidenceResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/SecondaryResidenceResponseDocument.cs new file mode 100644 index 0000000000..f2e4343706 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/SecondaryResidenceResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class SecondaryResidenceResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInResidenceResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public SecondaryResidenceResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.SecondaryResidenceResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.SecondaryResidenceResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInResidenceResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/StaffMemberCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/StaffMemberCollectionResponseDocument.cs new file mode 100644 index 0000000000..9c3ea492ff --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/StaffMemberCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class StaffMemberCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public StaffMemberCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.StaffMemberCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.StaffMemberCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInStaffMemberResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/StaffMemberIdentifierCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/StaffMemberIdentifierCollectionResponseDocument.cs new file mode 100644 index 0000000000..f8a7cfbd82 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/StaffMemberIdentifierCollectionResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class StaffMemberIdentifierCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public StaffMemberIdentifierCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.StaffMemberIdentifierCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.StaffMemberIdentifierCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.StaffMemberIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/StaffMemberIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/StaffMemberIdentifierInRequest.cs new file mode 100644 index 0000000000..1b4a907768 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/StaffMemberIdentifierInRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class StaffMemberIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.StaffMemberIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.StaffMemberIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/StaffMemberIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/StaffMemberIdentifierInResponse.cs new file mode 100644 index 0000000000..62883644c0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/StaffMemberIdentifierInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class StaffMemberIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.StaffMemberResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public StaffMemberIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.StaffMemberIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.StaffMemberIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/StaffMemberResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/StaffMemberResourceType.cs new file mode 100644 index 0000000000..80be2f02de --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/StaffMemberResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum StaffMemberResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "staffMembers")] + #pragma warning disable CS1591 + StaffMembers, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyBuildingInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyBuildingInRequest.cs new file mode 100644 index 0000000000..036073ef95 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyBuildingInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyBuildingInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyBuildingInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyBuildingInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyBuildingInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BuildingIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyBuildingInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyBuildingInResponse.cs new file mode 100644 index 0000000000..13c72202ae --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyBuildingInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyBuildingInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyBuildingInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyBuildingInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyBuildingInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.BuildingIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyRoadInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyRoadInRequest.cs new file mode 100644 index 0000000000..7069db6687 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyRoadInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyRoadInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyRoadInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoadInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoadInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoadIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyRoadInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyRoadInResponse.cs new file mode 100644 index 0000000000..165e536a50 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyRoadInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyRoadInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyRoadInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoadInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoadInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoadIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyRoomInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyRoomInRequest.cs new file mode 100644 index 0000000000..c2dea650f2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyRoomInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyRoomInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyRoomInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyRoomInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyRoomInResponse.cs new file mode 100644 index 0000000000..10acdbcdb9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyRoomInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyRoomInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyRoomInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyStaffMemberInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyStaffMemberInRequest.cs new file mode 100644 index 0000000000..ff897a120b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyStaffMemberInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyStaffMemberInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyStaffMemberInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyStaffMemberInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyStaffMemberInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.StaffMemberIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyStaffMemberInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyStaffMemberInResponse.cs new file mode 100644 index 0000000000..c331bec45f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToManyStaffMemberInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyStaffMemberInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyStaffMemberInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyStaffMemberInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyStaffMemberInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.StaffMemberIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToOneResidenceInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToOneResidenceInRequest.cs new file mode 100644 index 0000000000..3b3ccf027a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToOneResidenceInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToOneResidenceInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierInRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToOneResidenceInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToOneResidenceInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToOneResidenceInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierInRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToOneResidenceInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToOneResidenceInResponse.cs new file mode 100644 index 0000000000..1cca5438d6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToOneResidenceInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToOneResidenceInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToOneResidenceInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToOneResidenceInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToOneResidenceInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToiletCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToiletCollectionResponseDocument.cs new file mode 100644 index 0000000000..b731297e9b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToiletCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToiletCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToiletCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToiletCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToiletCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInToiletResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToiletIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToiletIdentifierInRequest.cs new file mode 100644 index 0000000000..08c1fe8100 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToiletIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToiletIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToiletIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToiletIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToiletIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToiletIdentifierInResponse.cs new file mode 100644 index 0000000000..a35a5c20cd --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/ToiletIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToiletIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToiletIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToiletIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateBathroomRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateBathroomRequestDocument.cs new file mode 100644 index 0000000000..726afad270 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateBathroomRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateBathroomRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateBathroomRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateBathroomRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateBathroomRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateBathroomRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateBathroomRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateBedroomRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateBedroomRequestDocument.cs new file mode 100644 index 0000000000..c78736d1c4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateBedroomRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateBedroomRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateBedroomRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateBedroomRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateBedroomRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateBedroomRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateBedroomRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateBuildingRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateBuildingRequestDocument.cs new file mode 100644 index 0000000000..ffe2b9ed67 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateBuildingRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateBuildingRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateBuildingRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateBuildingRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateBuildingRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateBuildingRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateBuildingRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateCyclePathRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateCyclePathRequestDocument.cs new file mode 100644 index 0000000000..a217f3c240 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateCyclePathRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateCyclePathRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateCyclePathRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateCyclePathRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateCyclePathRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateCyclePathRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateCyclePathRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateDistrictRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateDistrictRequestDocument.cs new file mode 100644 index 0000000000..ed0e71615f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateDistrictRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateDistrictRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateDistrictRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateDistrictRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateDistrictRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateDistrictRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateDistrictRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateFamilyHomeRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateFamilyHomeRequestDocument.cs new file mode 100644 index 0000000000..c4a9b7c3f3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateFamilyHomeRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateFamilyHomeRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateFamilyHomeRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateFamilyHomeRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateFamilyHomeRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateFamilyHomeRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateFamilyHomeRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateKitchenRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateKitchenRequestDocument.cs new file mode 100644 index 0000000000..0959023ce2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateKitchenRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateKitchenRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateKitchenRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateKitchenRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateKitchenRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateKitchenRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateKitchenRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateLivingRoomRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateLivingRoomRequestDocument.cs new file mode 100644 index 0000000000..16ff2af485 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateLivingRoomRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateLivingRoomRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateLivingRoomRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateLivingRoomRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateLivingRoomRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateLivingRoomRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateLivingRoomRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateMansionRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateMansionRequestDocument.cs new file mode 100644 index 0000000000..6202763be1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateMansionRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateMansionRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateMansionRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateMansionRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateMansionRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateMansionRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateMansionRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateResidenceRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateResidenceRequestDocument.cs new file mode 100644 index 0000000000..2886cdaade --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateResidenceRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateResidenceRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateResidenceRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateResidenceRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateResidenceRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateResidenceRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateResidenceRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateRoadRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateRoadRequestDocument.cs new file mode 100644 index 0000000000..98949c3fdc --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateRoadRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateRoadRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateRoadRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateRoadRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateRoadRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateRoadRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateRoadRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateRoomRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateRoomRequestDocument.cs new file mode 100644 index 0000000000..986853bf88 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateRoomRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateRoomRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateRoomRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateRoomRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateRoomRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateRoomRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateRoomRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateStaffMemberRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateStaffMemberRequestDocument.cs new file mode 100644 index 0000000000..92032d0115 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateStaffMemberRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateStaffMemberRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateStaffMemberRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateStaffMemberRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateStaffMemberRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateStaffMemberRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateStaffMemberRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateToiletRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateToiletRequestDocument.cs new file mode 100644 index 0000000000..6ff7e5eb43 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Models/UpdateToiletRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateToiletRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateToiletRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateToiletRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateToiletRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateToiletRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.DataInUpdateToiletRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/NoOperationsInheritanceClient.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/NoOperationsInheritanceClient.cs new file mode 100644 index 0000000000..671f89ce4b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/NoOperationsInheritanceClient.cs @@ -0,0 +1,152 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using Microsoft.Kiota.Serialization.Form; +using Microsoft.Kiota.Serialization.Json; +using Microsoft.Kiota.Serialization.Multipart; +using Microsoft.Kiota.Serialization.Text; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Buildings; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.CyclePaths; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Operations; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Roads; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.StaffMembers; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode +{ + /// + /// The main entry point of the SDK, exposes the configuration and the fluent API. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class NoOperationsInheritanceClient : BaseRequestBuilder + { + /// The bathrooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.BathroomsRequestBuilder Bathrooms + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bathrooms.BathroomsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The bedrooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.BedroomsRequestBuilder Bedrooms + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Bedrooms.BedroomsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The buildings property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Buildings.BuildingsRequestBuilder Buildings + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Buildings.BuildingsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The cyclePaths property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.CyclePaths.CyclePathsRequestBuilder CyclePaths + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.CyclePaths.CyclePathsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The districts property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.DistrictsRequestBuilder Districts + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Districts.DistrictsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The familyHomes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.FamilyHomesRequestBuilder FamilyHomes + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.FamilyHomes.FamilyHomesRequestBuilder(PathParameters, RequestAdapter); + } + + /// The kitchens property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.KitchensRequestBuilder Kitchens + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Kitchens.KitchensRequestBuilder(PathParameters, RequestAdapter); + } + + /// The livingRooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.LivingRoomsRequestBuilder LivingRooms + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.LivingRooms.LivingRoomsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The mansions property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.MansionsRequestBuilder Mansions + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Mansions.MansionsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The operations property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Operations.OperationsRequestBuilder Operations + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Operations.OperationsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The residences property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.ResidencesRequestBuilder Residences + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.ResidencesRequestBuilder(PathParameters, RequestAdapter); + } + + /// The roads property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Roads.RoadsRequestBuilder Roads + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Roads.RoadsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The rooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.RoomsRequestBuilder Rooms + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.RoomsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The staffMembers property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.StaffMembers.StaffMembersRequestBuilder StaffMembers + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.StaffMembers.StaffMembersRequestBuilder(PathParameters, RequestAdapter); + } + + /// The toilets property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.ToiletsRequestBuilder Toilets + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.ToiletsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The backing store to use for the models. + /// The request adapter to use to execute the requests. + public NoOperationsInheritanceClient(IRequestAdapter requestAdapter, IBackingStoreFactory backingStore = default) : base(requestAdapter, "{+baseurl}", new Dictionary()) + { + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + if (string.IsNullOrEmpty(RequestAdapter.BaseUrl)) + { + RequestAdapter.BaseUrl = "http://localhost"; + } + PathParameters.TryAdd("baseurl", RequestAdapter.BaseUrl); + RequestAdapter.EnableBackingStore(backingStore); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Operations/OperationsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Operations/OperationsRequestBuilder.cs new file mode 100644 index 0000000000..dd67d2c937 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Operations/OperationsRequestBuilder.cs @@ -0,0 +1,94 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Operations +{ + /// + /// Builds and executes requests for operations under \operations + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OperationsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public OperationsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/operations", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public OperationsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/operations", rawUrl) + { + } + + /// + /// Performs multiple mutations in a linear and atomic manner. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.OperationsRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.OperationsResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Performs multiple mutations in a linear and atomic manner. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.OperationsRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=atomic;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=atomic;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Operations.OperationsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Operations.OperationsRequestBuilder(rawUrl, RequestAdapter); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Residences/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Residences/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..3af9fe3880 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Residences/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.Item.Relationships.Rooms; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \residences\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The rooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.Item.Relationships.Rooms.RoomsRequestBuilder Rooms + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.Item.Relationships.Rooms.RoomsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/residences/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/residences/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Residences/Item/Relationships/Rooms/RoomsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Residences/Item/Relationships/Rooms/RoomsRequestBuilder.cs new file mode 100644 index 0000000000..c7d5273362 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Residences/Item/Relationships/Rooms/RoomsRequestBuilder.cs @@ -0,0 +1,248 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.Item.Relationships.Rooms +{ + /// + /// Builds and executes requests for operations under \residences\{id}\relationships\rooms + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/residences/{id}/relationships/rooms{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/residences/{id}/relationships/rooms{?query*}", rawUrl) + { + } + + /// + /// Removes existing rooms from the rooms relationship of an individual residence. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task DeleteAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToDeleteRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related room identities of an individual residence's rooms relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomIdentifierCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns existing rooms to the rooms relationship of an individual residence. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Adds existing rooms to the rooms relationship of an individual residence. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Removes existing rooms from the rooms relationship of an individual residence. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Retrieves the related room identities of an individual residence's rooms relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns existing rooms to the rooms relationship of an individual residence. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Adds existing rooms to the rooms relationship of an individual residence. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.Item.Relationships.Rooms.RoomsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.Item.Relationships.Rooms.RoomsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related room identities of an individual residence's rooms relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Residences/Item/ResidencesItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Residences/Item/ResidencesItemRequestBuilder.cs new file mode 100644 index 0000000000..cca0332c9e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Residences/Item/ResidencesItemRequestBuilder.cs @@ -0,0 +1,223 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.Item.Relationships; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.Item.Rooms; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.Item +{ + /// + /// Builds and executes requests for operations under \residences\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidencesItemRequestBuilder : BaseRequestBuilder + { + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The rooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.Item.Rooms.RoomsRequestBuilder Rooms + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.Item.Rooms.RoomsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ResidencesItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/residences/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ResidencesItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/residences/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing residence by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual residence by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryResidenceResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing residence. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateResidenceRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryResidenceResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing residence by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual residence by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing residence. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateResidenceRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.Item.ResidencesItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.Item.ResidencesItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual residence by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidencesItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidencesItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing residence. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidencesItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Residences/Item/Rooms/RoomsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Residences/Item/Rooms/RoomsRequestBuilder.cs new file mode 100644 index 0000000000..855e716c4e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Residences/Item/Rooms/RoomsRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.Item.Rooms +{ + /// + /// Builds and executes requests for operations under \residences\{id}\rooms + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/residences/{id}/rooms{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/residences/{id}/rooms{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related rooms of an individual residence's rooms relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related rooms of an individual residence's rooms relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.Item.Rooms.RoomsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.Item.Rooms.RoomsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related rooms of an individual residence's rooms relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Residences/ResidencesRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Residences/ResidencesRequestBuilder.cs new file mode 100644 index 0000000000..c3d052fc9c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Residences/ResidencesRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences +{ + /// + /// Builds and executes requests for operations under \residences + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidencesRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.residences.item collection + /// The identifier of the residence to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.Item.ResidencesItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.Item.ResidencesItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ResidencesRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/residences{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ResidencesRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/residences{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of residences. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new residence. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateResidenceRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryResidenceResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of residences. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new residence. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateResidenceRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.ResidencesRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Residences.ResidencesRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of residences. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidencesRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidencesRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new residence. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidencesRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Roads/Item/RoadsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Roads/Item/RoadsItemRequestBuilder.cs new file mode 100644 index 0000000000..a7f4fb2f39 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Roads/Item/RoadsItemRequestBuilder.cs @@ -0,0 +1,209 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Roads.Item +{ + /// + /// Builds and executes requests for operations under \roads\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoadsItemRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RoadsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/roads/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RoadsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/roads/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing road by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual road by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryRoadResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing road. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateRoadRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryRoadResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing road by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual road by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing road. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateRoadRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Roads.Item.RoadsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Roads.Item.RoadsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual road by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoadsItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoadsItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing road. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoadsItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Roads/RoadsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Roads/RoadsRequestBuilder.cs new file mode 100644 index 0000000000..183c993c2d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Roads/RoadsRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Roads.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Roads +{ + /// + /// Builds and executes requests for operations under \roads + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoadsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.roads.item collection + /// The identifier of the road to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Roads.Item.RoadsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Roads.Item.RoadsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RoadsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/roads{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RoadsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/roads{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of roads. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoadCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new road. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateRoadRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryRoadResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of roads. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new road. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateRoadRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Roads.RoadsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Roads.RoadsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of roads. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoadsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoadsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new road. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoadsRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Rooms/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Rooms/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..eb1ede6779 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Rooms/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.Item.Relationships.Residence; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \rooms\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.Item.Relationships.Residence.ResidenceRequestBuilder Residence + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.Item.Relationships.Residence.ResidenceRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/rooms/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/rooms/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Rooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Rooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs new file mode 100644 index 0000000000..709d7eed62 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Rooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs @@ -0,0 +1,168 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.Item.Relationships.Residence +{ + /// + /// Builds and executes requests for operations under \rooms\{id}\relationships\residence + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/rooms/{id}/relationships/residence{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/rooms/{id}/relationships/residence{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related residence identity of an individual room's residence relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns an existing residence to the residence relationship of an individual room. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related residence identity of an individual room's residence relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns an existing residence to the residence relationship of an individual room. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.Item.Relationships.Residence.ResidenceRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.Item.Relationships.Residence.ResidenceRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related residence identity of an individual room's residence relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Rooms/Item/Residence/ResidenceRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Rooms/Item/Residence/ResidenceRequestBuilder.cs new file mode 100644 index 0000000000..c204476e01 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Rooms/Item/Residence/ResidenceRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.Item.Residence +{ + /// + /// Builds and executes requests for operations under \rooms\{id}\residence + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/rooms/{id}/residence{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/rooms/{id}/residence{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related residence of an individual room's residence relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.SecondaryResidenceResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related residence of an individual room's residence relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.Item.Residence.ResidenceRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.Item.Residence.ResidenceRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related residence of an individual room's residence relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Rooms/Item/RoomsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Rooms/Item/RoomsItemRequestBuilder.cs new file mode 100644 index 0000000000..3d79d4361e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Rooms/Item/RoomsItemRequestBuilder.cs @@ -0,0 +1,223 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.Item.Relationships; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.Item.Residence; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.Item +{ + /// + /// Builds and executes requests for operations under \rooms\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsItemRequestBuilder : BaseRequestBuilder + { + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.Item.Residence.ResidenceRequestBuilder Residence + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.Item.Residence.ResidenceRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RoomsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/rooms/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RoomsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/rooms/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing room by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual room by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryRoomResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing room. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateRoomRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryRoomResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing room by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual room by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing room. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateRoomRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.Item.RoomsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.Item.RoomsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual room by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing room. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Rooms/RoomsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Rooms/RoomsRequestBuilder.cs new file mode 100644 index 0000000000..d94b753ccb --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Rooms/RoomsRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms +{ + /// + /// Builds and executes requests for operations under \rooms + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.rooms.item collection + /// The identifier of the room to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.Item.RoomsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.Item.RoomsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/rooms{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/rooms{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of rooms. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.RoomCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new room. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateRoomRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryRoomResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of rooms. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new room. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateRoomRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.RoomsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Rooms.RoomsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of rooms. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new room. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/StaffMembers/Item/StaffMembersItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/StaffMembers/Item/StaffMembersItemRequestBuilder.cs new file mode 100644 index 0000000000..49a8467e6d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/StaffMembers/Item/StaffMembersItemRequestBuilder.cs @@ -0,0 +1,209 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.StaffMembers.Item +{ + /// + /// Builds and executes requests for operations under \staffMembers\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class StaffMembersItemRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public StaffMembersItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/staffMembers/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public StaffMembersItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/staffMembers/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing staffMember by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual staffMember by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryStaffMemberResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing staffMember. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateStaffMemberRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryStaffMemberResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing staffMember by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual staffMember by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing staffMember. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateStaffMemberRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.StaffMembers.Item.StaffMembersItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.StaffMembers.Item.StaffMembersItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual staffMember by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class StaffMembersItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class StaffMembersItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing staffMember. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class StaffMembersItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/StaffMembers/StaffMembersRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/StaffMembers/StaffMembersRequestBuilder.cs new file mode 100644 index 0000000000..0401dfc38d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/StaffMembers/StaffMembersRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.StaffMembers.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.StaffMembers +{ + /// + /// Builds and executes requests for operations under \staffMembers + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class StaffMembersRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.staffMembers.item collection + /// The identifier of the staffMember to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.StaffMembers.Item.StaffMembersItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.StaffMembers.Item.StaffMembersItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public StaffMembersRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/staffMembers{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public StaffMembersRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/staffMembers{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of staffMembers. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.StaffMemberCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new staffMember. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateStaffMemberRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryStaffMemberResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of staffMembers. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new staffMember. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateStaffMemberRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.StaffMembers.StaffMembersRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.StaffMembers.StaffMembersRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of staffMembers. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class StaffMembersRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class StaffMembersRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new staffMember. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class StaffMembersRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Toilets/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Toilets/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..a49d8d42db --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Toilets/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.Item.Relationships.Residence; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \toilets\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.Item.Relationships.Residence.ResidenceRequestBuilder Residence + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.Item.Relationships.Residence.ResidenceRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/toilets/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/toilets/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Toilets/Item/Relationships/Residence/ResidenceRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Toilets/Item/Relationships/Residence/ResidenceRequestBuilder.cs new file mode 100644 index 0000000000..cfb0d5a17e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Toilets/Item/Relationships/Residence/ResidenceRequestBuilder.cs @@ -0,0 +1,168 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.Item.Relationships.Residence +{ + /// + /// Builds and executes requests for operations under \toilets\{id}\relationships\residence + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/toilets/{id}/relationships/residence{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/toilets/{id}/relationships/residence{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related residence identity of an individual toilet's residence relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ResidenceIdentifierResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns an existing residence to the residence relationship of an individual toilet. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related residence identity of an individual toilet's residence relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns an existing residence to the residence relationship of an individual toilet. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.Item.Relationships.Residence.ResidenceRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.Item.Relationships.Residence.ResidenceRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related residence identity of an individual toilet's residence relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Toilets/Item/Residence/ResidenceRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Toilets/Item/Residence/ResidenceRequestBuilder.cs new file mode 100644 index 0000000000..10551d094c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Toilets/Item/Residence/ResidenceRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.Item.Residence +{ + /// + /// Builds and executes requests for operations under \toilets\{id}\residence + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/toilets/{id}/residence{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/toilets/{id}/residence{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related residence of an individual toilet's residence relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.SecondaryResidenceResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related residence of an individual toilet's residence relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.Item.Residence.ResidenceRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.Item.Residence.ResidenceRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related residence of an individual toilet's residence relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Toilets/Item/ToiletsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Toilets/Item/ToiletsItemRequestBuilder.cs new file mode 100644 index 0000000000..e39bd675f1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Toilets/Item/ToiletsItemRequestBuilder.cs @@ -0,0 +1,223 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.Item.Relationships; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.Item.Residence; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.Item +{ + /// + /// Builds and executes requests for operations under \toilets\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ToiletsItemRequestBuilder : BaseRequestBuilder + { + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.Item.Residence.ResidenceRequestBuilder Residence + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.Item.Residence.ResidenceRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ToiletsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/toilets/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ToiletsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/toilets/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing toilet by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual toilet by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryToiletResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing toilet. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateToiletRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryToiletResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing toilet by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Retrieves an individual toilet by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Updates an existing toilet. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.UpdateToiletRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.Item.ToiletsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.Item.ToiletsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual toilet by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ToiletsItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ToiletsItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Updates an existing toilet. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ToiletsItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Toilets/ToiletsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Toilets/ToiletsRequestBuilder.cs new file mode 100644 index 0000000000..714b2e4833 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/Toilets/ToiletsRequestBuilder.cs @@ -0,0 +1,194 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets +{ + /// + /// Builds and executes requests for operations under \toilets + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ToiletsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.toilets.item collection + /// The identifier of the toilet to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.Item.ToiletsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.Item.ToiletsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ToiletsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/toilets{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ToiletsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/toilets{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of toilets. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ToiletCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new toilet. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateToiletRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.PrimaryToiletResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of toilets. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Creates a new toilet. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models.CreateToiletRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.ToiletsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Toilets.ToiletsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of toilets. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ToiletsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ToiletsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Creates a new toilet. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ToiletsRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/ResourceInheritanceTests.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/ResourceInheritanceTests.cs new file mode 100644 index 0000000000..7c93ad95cb --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/ResourceInheritanceTests.cs @@ -0,0 +1,961 @@ +using FluentAssertions; +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.Resources; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode; +using OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.ResourceInheritance; +using OpenApiTests.ResourceInheritance.Models; +using OpenApiTests.ResourceInheritance.NoOperations; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations; + +public sealed class ResourceInheritanceTests + : IClassFixture, ResourceInheritanceDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, ResourceInheritanceDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly ResourceInheritanceFakers _fakers = new(); + + public ResourceInheritanceTests(IntegrationTestContext, ResourceInheritanceDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseInheritanceControllers(false); + + testContext.ConfigureServices(services => + { + services.AddScoped(typeof(IResourceChangeTracker<>), typeof(NeverSameResourceChangeTracker<>)); + + services.AddSingleton(); + services.AddSingleton(); + }); + } + + [Fact] + public async Task Can_get_primary_resources_at_abstract_endpoint() + { + // Arrange + Residence residence = _fakers.Residence.GenerateOne(); + Mansion mansion = _fakers.Mansion.GenerateOne(); + FamilyHome familyHome = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Buildings.AddRange(residence, mansion, familyHome); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new NoOperationsInheritanceClient(requestAdapter); + + // Act + BuildingCollectionResponseDocument? response = await apiClient.Buildings.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(3); + + response.Data.OfType().Should().ContainSingle(data => data.Id == residence.StringId).Subject.With(data => + { + AttributesInResidenceResponse attributes = data.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(residence.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(residence.NumberOfResidents); + + RelationshipsInResidenceResponse relationships = data.Relationships.Should().BeOfType().Subject; + + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().BeNull(); + }); + + response.Data.OfType().Should().ContainSingle(data => data.Id == mansion.StringId).Subject.With(data => + { + AttributesInMansionResponse attributes = data.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(mansion.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(mansion.NumberOfResidents); + attributes.OwnerName.Should().Be(mansion.OwnerName); + + RelationshipsInMansionResponse relationships = data.Relationships.Should().BeOfType().Subject; + + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().BeNull(); + + relationships.Staff.Should().NotBeNull(); + relationships.Staff.Data.Should().BeNull(); + }); + + response.Data.OfType().Should().ContainSingle(data => data.Id == familyHome.StringId).Subject.With(data => + { + AttributesInFamilyHomeResponse attributes = data.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(familyHome.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(familyHome.NumberOfResidents); + attributes.FloorCount.Should().Be(familyHome.FloorCount); + + RelationshipsInFamilyHomeResponse relationships = data.Relationships.Should().BeOfType().Subject; + + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().BeNull(); + }); + } + + [Fact] + public async Task Can_get_primary_resources_at_concrete_base_endpoint() + { + // Arrange + Road road = _fakers.Road.GenerateOne(); + CyclePath cyclePath = _fakers.CyclePath.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Roads.AddRange(road, cyclePath); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new NoOperationsInheritanceClient(requestAdapter); + + // Act + RoadCollectionResponseDocument? response = await apiClient.Roads.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(2); + + response.Data.Should().ContainSingle(data => data.Id == road.StringId).Subject.With(data => + { + AttributesInRoadResponse? attributes = data.Attributes.Should().BeOfType().Subject; + + ((decimal?)attributes.LengthInMeters).Should().BeApproximately(road.LengthInMeters); + + data.Relationships.Should().BeNull(); + }); + + response.Data.OfType().Should().ContainSingle(data => data.Id == cyclePath.StringId).Subject.With(data => + { + AttributesInCyclePathResponse attributes = data.Attributes.Should().BeOfType().Subject; + + ((decimal?)attributes.LengthInMeters).Should().BeApproximately(cyclePath.LengthInMeters); + attributes.HasLaneForPedestrians.Should().Be(cyclePath.HasLaneForPedestrians); + + data.Relationships.Should().BeNull(); + }); + } + + [Fact] + public async Task Can_get_primary_resources_at_concrete_derived_endpoint() + { + // Arrange + FamilyHome familyHome1 = _fakers.FamilyHome.GenerateOne(); + FamilyHome familyHome2 = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Buildings.AddRange(familyHome1, familyHome2); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new NoOperationsInheritanceClient(requestAdapter); + + // Act + FamilyHomeCollectionResponseDocument? response = await apiClient.FamilyHomes.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(2); + + response.Data.Should().ContainSingle(data => data.Id == familyHome1.StringId).Subject.With(data => + { + AttributesInResidenceResponse attributes = data.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(familyHome1.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(familyHome1.NumberOfResidents); + + RelationshipsInResidenceResponse relationships = data.Relationships.Should().BeOfType().Subject; + + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().BeNull(); + }); + + response.Data.Should().ContainSingle(data => data.Id == familyHome2.StringId).Subject.With(data => + { + AttributesInResidenceResponse attributes = data.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(familyHome2.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(familyHome2.NumberOfResidents); + + RelationshipsInResidenceResponse relationships = data.Relationships.Should().BeOfType().Subject; + + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().BeNull(); + }); + } + + [Fact] + public async Task Can_get_primary_resource_at_abstract_endpoint() + { + // Arrange + Mansion mansion = _fakers.Mansion.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Buildings.Add(mansion); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new NoOperationsInheritanceClient(requestAdapter); + + // Act + PrimaryBuildingResponseDocument? response = await apiClient.Buildings[mansion.StringId!].GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().BeOfType(); + response.Data.Id.Should().Be(mansion.StringId); + + response.Data.Attributes.Should().BeOfType().Subject.With(attributes => + { + attributes.SurfaceInSquareMeters.Should().Be(mansion.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(mansion.NumberOfResidents); + attributes.OwnerName.Should().Be(mansion.OwnerName); + }); + + response.Data.Relationships.Should().BeOfType().Subject.With(relationships => + { + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().BeNull(); + + relationships.Staff.Should().NotBeNull(); + relationships.Staff.Data.Should().BeNull(); + }); + } + + [Fact] + public async Task Can_get_primary_resource_at_concrete_base_endpoint() + { + // Arrange + CyclePath cyclePath = _fakers.CyclePath.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Roads.Add(cyclePath); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new NoOperationsInheritanceClient(requestAdapter); + + // Act + PrimaryRoadResponseDocument? response = await apiClient.Roads[cyclePath.StringId!].GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().BeOfType(); + response.Data.Id.Should().Be(cyclePath.StringId); + + response.Data.Attributes.Should().BeOfType().Subject.With(attributes => + { + ((decimal?)attributes.LengthInMeters).Should().BeApproximately(cyclePath.LengthInMeters); + attributes.HasLaneForPedestrians.Should().Be(cyclePath.HasLaneForPedestrians); + }); + + response.Data.Relationships.Should().BeNull(); + } + + [Fact] + public async Task Can_get_primary_resource_at_concrete_derived_endpoint() + { + // Arrange + FamilyHome familyHome = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Buildings.Add(familyHome); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new NoOperationsInheritanceClient(requestAdapter); + + // Act + PrimaryFamilyHomeResponseDocument? response = await apiClient.FamilyHomes[familyHome.StringId!].GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().BeOfType(); + response.Data.Id.Should().Be(familyHome.StringId); + + response.Data.Attributes.Should().BeOfType().Subject.With(attributes => + { + attributes.SurfaceInSquareMeters.Should().Be(familyHome.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(familyHome.NumberOfResidents); + }); + + response.Data.Relationships.Should().BeOfType().Subject.With(relationships => + { + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().BeNull(); + }); + } + + [Fact] + public async Task Can_get_secondary_resource_at_abstract_base_endpoint() + { + // Arrange + Bedroom bedroom = _fakers.Bedroom.GenerateOne(); + FamilyHome familyHome = _fakers.FamilyHome.GenerateOne(); + bedroom.Residence = familyHome; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Rooms.Add(bedroom); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new NoOperationsInheritanceClient(requestAdapter); + + // Act + SecondaryResidenceResponseDocument? response = await apiClient.Rooms[bedroom.StringId!].Residence.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().BeOfType(); + response.Data.Id.Should().Be(bedroom.Residence.StringId); + + response.Data.Attributes.Should().BeOfType().Subject.With(attributes => + { + attributes.SurfaceInSquareMeters.Should().Be(familyHome.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(familyHome.NumberOfResidents); + attributes.FloorCount.Should().Be(familyHome.FloorCount); + }); + + response.Data.Relationships.Should().BeOfType().Subject.With(relationships => + { + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().BeNull(); + }); + } + + [Fact] + public async Task Can_get_secondary_resource_at_concrete_derived_endpoint() + { + // Arrange + Bedroom bedroom = _fakers.Bedroom.GenerateOne(); + FamilyHome familyHome = _fakers.FamilyHome.GenerateOne(); + bedroom.Residence = familyHome; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Rooms.Add(bedroom); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new NoOperationsInheritanceClient(requestAdapter); + + // Act + SecondaryResidenceResponseDocument? response = await apiClient.Bedrooms[bedroom.StringId!].Residence.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().BeOfType(); + response.Data.Id.Should().Be(bedroom.Residence.StringId); + + response.Data.Attributes.Should().BeOfType().Subject.With(attributes => + { + attributes.SurfaceInSquareMeters.Should().Be(familyHome.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(familyHome.NumberOfResidents); + attributes.FloorCount.Should().Be(familyHome.FloorCount); + }); + + response.Data.Relationships.Should().BeOfType().Subject.With(relationships => + { + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().BeNull(); + }); + } + + [Fact] + public async Task Can_get_secondary_resources_at_concrete_base_endpoint() + { + // Arrange + Kitchen kitchen = _fakers.Kitchen.GenerateOne(); + Bedroom bedroom = _fakers.Bedroom.GenerateOne(); + + FamilyHome familyHome = _fakers.FamilyHome.GenerateOne(); + familyHome.Rooms.Add(kitchen); + familyHome.Rooms.Add(bedroom); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.FamilyHomes.Add(familyHome); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new NoOperationsInheritanceClient(requestAdapter); + + // Act + RoomCollectionResponseDocument? response = await apiClient.Residences[familyHome.StringId!].Rooms.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(2); + + response.Data.OfType().Should().ContainSingle(data => data.Id == kitchen.StringId).Subject.With(data => + { + AttributesInKitchenResponse attributes = data.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(kitchen.SurfaceInSquareMeters); + attributes.HasPantry.Should().Be(kitchen.HasPantry); + + RelationshipsInKitchenResponse relationships = data.Relationships.Should().BeOfType().Subject; + + relationships.Residence.Should().NotBeNull(); + relationships.Residence.Data.Should().BeNull(); + }); + + response.Data.OfType().Should().ContainSingle(data => data.Id == bedroom.StringId).Subject.With(data => + { + AttributesInBedroomResponse attributes = data.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(bedroom.SurfaceInSquareMeters); + attributes.BedCount.Should().Be(bedroom.BedCount); + + RelationshipsInBedroomResponse relationships = data.Relationships.Should().BeOfType().Subject; + + relationships.Residence.Should().NotBeNull(); + relationships.Residence.Data.Should().BeNull(); + }); + } + + [Fact] + public async Task Can_get_secondary_resources_at_concrete_derived_endpoint() + { + // Arrange + Bathroom bathroom = _fakers.Bathroom.GenerateOne(); + Toilet toilet = _fakers.Toilet.GenerateOne(); + + Mansion mansion = _fakers.Mansion.GenerateOne(); + mansion.Rooms.Add(bathroom); + mansion.Rooms.Add(toilet); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(mansion); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new NoOperationsInheritanceClient(requestAdapter); + + // Act + RoomCollectionResponseDocument? response = await apiClient.Mansions[mansion.StringId!].Rooms.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(2); + + response.Data.OfType().Should().ContainSingle(data => data.Id == bathroom.StringId).Subject.With(data => + { + AttributesInBathroomResponse attributes = data.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(bathroom.SurfaceInSquareMeters); + attributes.HasBath.Should().Be(bathroom.HasBath); + + RelationshipsInBathroomResponse relationships = data.Relationships.Should().BeOfType().Subject; + + relationships.Residence.Should().NotBeNull(); + relationships.Residence.Data.Should().BeNull(); + }); + + response.Data.OfType().Should().ContainSingle(data => data.Id == toilet.StringId).Subject.With(data => + { + AttributesInToiletResponse attributes = data.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(toilet.SurfaceInSquareMeters); + attributes.HasSink.Should().Be(toilet.HasSink); + + RelationshipsInToiletResponse relationships = data.Relationships.Should().BeOfType().Subject; + + relationships.Residence.Should().NotBeNull(); + relationships.Residence.Data.Should().BeNull(); + }); + } + + [Fact] + public async Task Can_create_concrete_base_resource_at_abstract_endpoint() + { + // Arrange + double newLengthInMeters = (double)_fakers.Road.GenerateOne().LengthInMeters; + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new NoOperationsInheritanceClient(requestAdapter); + + CreateRoadRequestDocument requestBody = new() + { + Data = new DataInCreateRoadRequest + { + Type = ResourceType.Roads, + Attributes = new AttributesInCreateRoadRequest + { + LengthInMeters = newLengthInMeters + } + } + }; + + // Act + PrimaryRoadResponseDocument? response = await apiClient.Roads.PostAsync(requestBody); + + // Assert + response.Should().NotBeNull(); + + DataInRoadResponse roadData = response.Data.Should().BeOfType().Subject; + + AttributesInRoadResponse roadAttributes = roadData.Attributes.Should().BeOfType().Subject; + roadAttributes.LengthInMeters.Should().Be(newLengthInMeters); + + roadData.Relationships.Should().BeNull(); + + long newRoadId = long.Parse(roadData.Id.Should().NotBeNull().And.Subject); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Road roadInDatabase = await dbContext.Roads.FirstWithIdAsync(newRoadId); + + roadInDatabase.LengthInMeters.Should().Be((decimal)newLengthInMeters); + }); + } + + [Fact] + public async Task Can_create_concrete_derived_resource_at_abstract_endpoint_with_relationships_and_includes() + { + // Arrange + Bedroom existingBedroom1 = _fakers.Bedroom.GenerateOne(); + Bedroom existingBedroom2 = _fakers.Bedroom.GenerateOne(); + LivingRoom existingLivingRoom = _fakers.LivingRoom.GenerateOne(); + + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + existingMansion.Rooms.Add(existingBedroom1); + existingMansion.Rooms.Add(existingBedroom2); + existingMansion.Rooms.Add(existingLivingRoom); + + FamilyHome newFamilyHome = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new NoOperationsInheritanceClient(requestAdapter); + + CreateBuildingRequestDocument requestBody = new() + { + Data = new DataInCreateFamilyHomeRequest + { + Type = ResourceType.FamilyHomes, + Attributes = new AttributesInCreateFamilyHomeRequest + { + SurfaceInSquareMeters = newFamilyHome.SurfaceInSquareMeters!.Value, + NumberOfResidents = newFamilyHome.NumberOfResidents!.Value, + FloorCount = newFamilyHome.FloorCount + }, + Relationships = new RelationshipsInCreateFamilyHomeRequest + { + Rooms = new ToManyRoomInRequest + { + Data = + [ + new RoomIdentifierInRequest + { + Type = ResourceType.Bedrooms, + Id = existingBedroom1.StringId! + }, + new RoomIdentifierInRequest + { + Type = ResourceType.Bedrooms, + Id = existingBedroom2.StringId! + }, + new RoomIdentifierInRequest + { + Type = ResourceType.LivingRooms, + Id = existingLivingRoom.StringId! + } + ] + } + } + } + }; + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["include"] = "rooms" + }); + + // Act + PrimaryBuildingResponseDocument? response = await apiClient.Buildings.PostAsync(requestBody); + + // Assert + response.Should().NotBeNull(); + + DataInFamilyHomeResponse familyHomeData = response.Data.Should().BeOfType().Subject; + + AttributesInFamilyHomeResponse familyHomeAttributes = familyHomeData.Attributes.Should().BeOfType().Subject; + familyHomeAttributes.SurfaceInSquareMeters.Should().Be(newFamilyHome.SurfaceInSquareMeters); + familyHomeAttributes.NumberOfResidents.Should().Be(newFamilyHome.NumberOfResidents); + familyHomeAttributes.FloorCount.Should().Be(newFamilyHome.FloorCount); + + RelationshipsInFamilyHomeResponse familyHomeRelationships = familyHomeData.Relationships.Should().BeOfType().Subject; + + familyHomeRelationships.Rooms.RefShould().NotBeNull().And.Subject.Data.With(roomData => + { + roomData.Should().HaveCount(3); + roomData.OfType().Should().ContainSingle(data => data.Id == existingBedroom1.StringId); + roomData.OfType().Should().ContainSingle(data => data.Id == existingBedroom2.StringId); + roomData.OfType().Should().ContainSingle(data => data.Id == existingLivingRoom.StringId); + }); + + long newFamilyHomeId = long.Parse(familyHomeData.Id.Should().NotBeNull().And.Subject); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + FamilyHome familyHomeInDatabase = await dbContext.FamilyHomes.Include(familyHome => familyHome.Rooms).FirstWithIdAsync(newFamilyHomeId); + + familyHomeInDatabase.SurfaceInSquareMeters.Should().Be(newFamilyHome.SurfaceInSquareMeters); + familyHomeInDatabase.NumberOfResidents.Should().Be(newFamilyHome.NumberOfResidents); + familyHomeInDatabase.FloorCount.Should().Be(newFamilyHome.FloorCount); + + familyHomeInDatabase.Rooms.Should().HaveCount(3); + familyHomeInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom1.Id); + familyHomeInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom2.Id); + familyHomeInDatabase.Rooms.OfType().Should().ContainSingle(livingRoom => livingRoom.Id == existingLivingRoom.Id); + }); + } + + [Fact] + public async Task Can_create_concrete_derived_resource_at_concrete_base_endpoint() + { + // Arrange + FamilyHome newFamilyHome = _fakers.FamilyHome.GenerateOne(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new NoOperationsInheritanceClient(requestAdapter); + + CreateResidenceRequestDocument requestBody = new() + { + Data = new DataInCreateFamilyHomeRequest + { + Type = ResourceType.FamilyHomes, + Attributes = new AttributesInCreateFamilyHomeRequest + { + SurfaceInSquareMeters = newFamilyHome.SurfaceInSquareMeters!.Value, + NumberOfResidents = newFamilyHome.NumberOfResidents!.Value, + FloorCount = newFamilyHome.FloorCount + } + } + }; + + // Act + PrimaryResidenceResponseDocument? response = await apiClient.Residences.PostAsync(requestBody); + + // Assert + response.Should().NotBeNull(); + + DataInFamilyHomeResponse familyHomeData = response.Data.Should().BeOfType().Subject; + + AttributesInFamilyHomeResponse familyHomeAttributes = familyHomeData.Attributes.Should().BeOfType().Subject; + familyHomeAttributes.SurfaceInSquareMeters.Should().Be(newFamilyHome.SurfaceInSquareMeters); + familyHomeAttributes.NumberOfResidents.Should().Be(newFamilyHome.NumberOfResidents); + familyHomeAttributes.FloorCount.Should().Be(newFamilyHome.FloorCount); + + RelationshipsInFamilyHomeResponse familyHomeRelationships = familyHomeData.Relationships.Should().BeOfType().Subject; + familyHomeRelationships.Rooms.Should().NotBeNull(); + + long newFamilyHomeId = long.Parse(familyHomeData.Id.Should().NotBeNull().And.Subject); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + FamilyHome familyHomeInDatabase = await dbContext.FamilyHomes.Include(familyHome => familyHome.Rooms).FirstWithIdAsync(newFamilyHomeId); + + familyHomeInDatabase.SurfaceInSquareMeters.Should().Be(newFamilyHome.SurfaceInSquareMeters); + familyHomeInDatabase.NumberOfResidents.Should().Be(newFamilyHome.NumberOfResidents); + familyHomeInDatabase.FloorCount.Should().Be(newFamilyHome.FloorCount); + + familyHomeInDatabase.Rooms.Should().BeEmpty(); + }); + } + + [Fact] + public async Task Can_update_concrete_base_resource_at_abstract_endpoint() + { + // Arrange + Road existingRoad = _fakers.Road.GenerateOne(); + + double newLengthInMeters = (double)_fakers.Road.GenerateOne().LengthInMeters; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Roads.Add(existingRoad); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new NoOperationsInheritanceClient(requestAdapter); + + UpdateRoadRequestDocument requestBody = new() + { + Data = new DataInUpdateRoadRequest + { + Type = ResourceType.Roads, + Id = existingRoad.StringId!, + Attributes = new AttributesInUpdateRoadRequest + { + LengthInMeters = newLengthInMeters + } + } + }; + + // Act + PrimaryRoadResponseDocument? response = await apiClient.Roads[existingRoad.StringId!].PatchAsync(requestBody); + + // Assert + response.Should().NotBeNull(); + + DataInRoadResponse roadData = response.Data.Should().BeOfType().Subject; + + AttributesInRoadResponse roadAttributes = roadData.Attributes.Should().BeOfType().Subject; + roadAttributes.LengthInMeters.Should().Be(newLengthInMeters); + + roadData.Relationships.Should().BeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Road roadInDatabase = await dbContext.Roads.FirstWithIdAsync(existingRoad.Id); + + roadInDatabase.LengthInMeters.Should().Be((decimal)newLengthInMeters); + }); + } + + [Fact] + public async Task Can_update_concrete_derived_resource_at_abstract_endpoint_with_relationships_and_includes() + { + // Arrange + Bedroom existingBedroom1 = _fakers.Bedroom.GenerateOne(); + Bedroom existingBedroom2 = _fakers.Bedroom.GenerateOne(); + LivingRoom existingLivingRoom = _fakers.LivingRoom.GenerateOne(); + + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + existingMansion.Rooms.Add(existingBedroom1); + existingMansion.Rooms.Add(existingBedroom2); + existingMansion.Rooms.Add(existingLivingRoom); + + FamilyHome existingFamilyHome = _fakers.FamilyHome.GenerateOne(); + existingFamilyHome.Rooms.Add(_fakers.Kitchen.GenerateOne()); + + FamilyHome newFamilyHome = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + dbContext.FamilyHomes.Add(existingFamilyHome); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new NoOperationsInheritanceClient(requestAdapter); + + UpdateBuildingRequestDocument requestBody = new() + { + Data = new DataInUpdateFamilyHomeRequest + { + Type = ResourceType.FamilyHomes, + Id = existingFamilyHome.StringId!, + Attributes = new AttributesInUpdateFamilyHomeRequest + { + SurfaceInSquareMeters = newFamilyHome.SurfaceInSquareMeters!.Value, + NumberOfResidents = newFamilyHome.NumberOfResidents!.Value, + FloorCount = newFamilyHome.FloorCount + }, + Relationships = new RelationshipsInUpdateFamilyHomeRequest + { + Rooms = new ToManyRoomInRequest + { + Data = + [ + new RoomIdentifierInRequest + { + Type = ResourceType.Bedrooms, + Id = existingBedroom1.StringId! + }, + new RoomIdentifierInRequest + { + Type = ResourceType.Bedrooms, + Id = existingBedroom2.StringId! + }, + new RoomIdentifierInRequest + { + Type = ResourceType.LivingRooms, + Id = existingLivingRoom.StringId! + } + ] + } + } + } + }; + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["include"] = "rooms" + }); + + // Act + PrimaryBuildingResponseDocument? response = await apiClient.Buildings[existingFamilyHome.StringId!].PatchAsync(requestBody); + + // Assert + response.Should().NotBeNull(); + + DataInFamilyHomeResponse familyHomeData = response.Data.Should().BeOfType().Subject; + + AttributesInFamilyHomeResponse familyHomeAttributes = familyHomeData.Attributes.Should().BeOfType().Subject; + familyHomeAttributes.SurfaceInSquareMeters.Should().Be(newFamilyHome.SurfaceInSquareMeters); + familyHomeAttributes.NumberOfResidents.Should().Be(newFamilyHome.NumberOfResidents); + familyHomeAttributes.FloorCount.Should().Be(newFamilyHome.FloorCount); + + RelationshipsInFamilyHomeResponse familyHomeRelationships = familyHomeData.Relationships.Should().BeOfType().Subject; + + familyHomeRelationships.Rooms.RefShould().NotBeNull().And.Subject.Data.With(roomData => + { + roomData.Should().HaveCount(3); + roomData.OfType().Should().ContainSingle(data => data.Id == existingBedroom1.StringId); + roomData.OfType().Should().ContainSingle(data => data.Id == existingBedroom2.StringId); + roomData.OfType().Should().ContainSingle(data => data.Id == existingLivingRoom.StringId); + }); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + FamilyHome familyHomeInDatabase = await dbContext.FamilyHomes.Include(familyHome => familyHome.Rooms).FirstWithIdAsync(existingFamilyHome.Id); + + familyHomeInDatabase.SurfaceInSquareMeters.Should().Be(newFamilyHome.SurfaceInSquareMeters); + familyHomeInDatabase.NumberOfResidents.Should().Be(newFamilyHome.NumberOfResidents); + familyHomeInDatabase.FloorCount.Should().Be(newFamilyHome.FloorCount); + + familyHomeInDatabase.Rooms.Should().HaveCount(3); + familyHomeInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom1.Id); + familyHomeInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom2.Id); + familyHomeInDatabase.Rooms.OfType().Should().ContainSingle(livingRoom => livingRoom.Id == existingLivingRoom.Id); + }); + } + + [Fact] + public async Task Can_update_concrete_derived_resource_at_concrete_base_endpoint() + { + // Arrange + FamilyHome existingFamilyHome = _fakers.FamilyHome.GenerateOne(); + existingFamilyHome.Rooms.Add(_fakers.Kitchen.GenerateOne()); + + FamilyHome newFamilyHome = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.FamilyHomes.Add(existingFamilyHome); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new NoOperationsInheritanceClient(requestAdapter); + + UpdateBuildingRequestDocument requestBody = new() + { + Data = new DataInUpdateFamilyHomeRequest + { + Type = ResourceType.FamilyHomes, + Id = existingFamilyHome.StringId!, + Attributes = new AttributesInUpdateFamilyHomeRequest + { + SurfaceInSquareMeters = newFamilyHome.SurfaceInSquareMeters!.Value, + NumberOfResidents = newFamilyHome.NumberOfResidents!.Value, + FloorCount = newFamilyHome.FloorCount + } + } + }; + + // Act + PrimaryBuildingResponseDocument? response = await apiClient.Buildings[existingFamilyHome.StringId!].PatchAsync(requestBody); + + // Assert + response.Should().NotBeNull(); + + DataInFamilyHomeResponse familyHomeData = response.Data.Should().BeOfType().Subject; + + AttributesInFamilyHomeResponse familyHomeAttributes = familyHomeData.Attributes.Should().BeOfType().Subject; + familyHomeAttributes.SurfaceInSquareMeters.Should().Be(newFamilyHome.SurfaceInSquareMeters); + familyHomeAttributes.NumberOfResidents.Should().Be(newFamilyHome.NumberOfResidents); + familyHomeAttributes.FloorCount.Should().Be(newFamilyHome.FloorCount); + + RelationshipsInFamilyHomeResponse familyHomeRelationships = familyHomeData.Relationships.Should().BeOfType().Subject; + familyHomeRelationships.Rooms.Should().NotBeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + FamilyHome familyHomeInDatabase = await dbContext.FamilyHomes.Include(familyHome => familyHome.Rooms).FirstWithIdAsync(existingFamilyHome.Id); + + familyHomeInDatabase.SurfaceInSquareMeters.Should().Be(newFamilyHome.SurfaceInSquareMeters); + familyHomeInDatabase.NumberOfResidents.Should().Be(newFamilyHome.NumberOfResidents); + familyHomeInDatabase.FloorCount.Should().Be(newFamilyHome.FloorCount); + + familyHomeInDatabase.Rooms.Should().HaveCount(1); + familyHomeInDatabase.Rooms.OfType().Should().ContainSingle(kitchen => kitchen.Id == existingFamilyHome.Rooms.ElementAt(0).Id); + }); + } + + [Fact] + public async Task Can_delete_concrete_derived_resource_at_abstract_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new NoOperationsInheritanceClient(requestAdapter); + + // Act + await apiClient.Buildings[existingMansion.StringId!].DeleteAsync(); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + FamilyHome? familyHomeInDatabase = await dbContext.FamilyHomes.FirstWithIdOrDefaultAsync(existingMansion.Id); + + familyHomeInDatabase.Should().BeNull(); + }); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bathrooms/BathroomsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bathrooms/BathroomsRequestBuilder.cs new file mode 100644 index 0000000000..2faf4d95e9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bathrooms/BathroomsRequestBuilder.cs @@ -0,0 +1,52 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bathrooms.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bathrooms +{ + /// + /// Builds and executes requests for operations under \bathrooms + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BathroomsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.bathrooms.item collection + /// The identifier of the bathroom whose related residence identity to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bathrooms.Item.BathroomsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bathrooms.Item.BathroomsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public BathroomsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bathrooms", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public BathroomsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bathrooms", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bathrooms/Item/BathroomsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bathrooms/Item/BathroomsItemRequestBuilder.cs new file mode 100644 index 0000000000..28a422a10a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bathrooms/Item/BathroomsItemRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bathrooms.Item.Relationships; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bathrooms.Item +{ + /// + /// Builds and executes requests for operations under \bathrooms\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BathroomsItemRequestBuilder : BaseRequestBuilder + { + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bathrooms.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bathrooms.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public BathroomsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bathrooms/{id}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public BathroomsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bathrooms/{id}", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bathrooms/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bathrooms/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..3bc2420018 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bathrooms/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bathrooms.Item.Relationships.Residence; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bathrooms.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \bathrooms\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bathrooms.Item.Relationships.Residence.ResidenceRequestBuilder Residence + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bathrooms.Item.Relationships.Residence.ResidenceRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bathrooms/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bathrooms/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bathrooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bathrooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs new file mode 100644 index 0000000000..176f1eb2bb --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bathrooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs @@ -0,0 +1,168 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bathrooms.Item.Relationships.Residence +{ + /// + /// Builds and executes requests for operations under \bathrooms\{id}\relationships\residence + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bathrooms/{id}/relationships/residence{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bathrooms/{id}/relationships/residence{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related residence identity of an individual bathroom's residence relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns an existing residence to the residence relationship of an individual bathroom. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related residence identity of an individual bathroom's residence relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns an existing residence to the residence relationship of an individual bathroom. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bathrooms.Item.Relationships.Residence.ResidenceRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bathrooms.Item.Relationships.Residence.ResidenceRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related residence identity of an individual bathroom's residence relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bedrooms/BedroomsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bedrooms/BedroomsRequestBuilder.cs new file mode 100644 index 0000000000..5e7e71c07b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bedrooms/BedroomsRequestBuilder.cs @@ -0,0 +1,52 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bedrooms.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bedrooms +{ + /// + /// Builds and executes requests for operations under \bedrooms + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BedroomsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.bedrooms.item collection + /// The identifier of the bedroom whose related residence identity to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bedrooms.Item.BedroomsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bedrooms.Item.BedroomsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public BedroomsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bedrooms", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public BedroomsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bedrooms", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bedrooms/Item/BedroomsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bedrooms/Item/BedroomsItemRequestBuilder.cs new file mode 100644 index 0000000000..46ba9a6b3b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bedrooms/Item/BedroomsItemRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bedrooms.Item.Relationships; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bedrooms.Item +{ + /// + /// Builds and executes requests for operations under \bedrooms\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BedroomsItemRequestBuilder : BaseRequestBuilder + { + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bedrooms.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bedrooms.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public BedroomsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bedrooms/{id}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public BedroomsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bedrooms/{id}", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bedrooms/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bedrooms/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..f90a7b878f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bedrooms/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bedrooms.Item.Relationships.Residence; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bedrooms.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \bedrooms\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bedrooms.Item.Relationships.Residence.ResidenceRequestBuilder Residence + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bedrooms.Item.Relationships.Residence.ResidenceRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bedrooms/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bedrooms/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bedrooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bedrooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs new file mode 100644 index 0000000000..f2e6fdc796 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Bedrooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs @@ -0,0 +1,168 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bedrooms.Item.Relationships.Residence +{ + /// + /// Builds and executes requests for operations under \bedrooms\{id}\relationships\residence + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bedrooms/{id}/relationships/residence{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/bedrooms/{id}/relationships/residence{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related residence identity of an individual bedroom's residence relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns an existing residence to the residence relationship of an individual bedroom. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related residence identity of an individual bedroom's residence relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns an existing residence to the residence relationship of an individual bedroom. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bedrooms.Item.Relationships.Residence.ResidenceRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bedrooms.Item.Relationships.Residence.ResidenceRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related residence identity of an individual bedroom's residence relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Districts/DistrictsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Districts/DistrictsRequestBuilder.cs new file mode 100644 index 0000000000..91cd94cb58 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Districts/DistrictsRequestBuilder.cs @@ -0,0 +1,52 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts +{ + /// + /// Builds and executes requests for operations under \districts + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class DistrictsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.districts.item collection + /// The identifier of the district whose related building identities to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts.Item.DistrictsItemRequestBuilder this[Guid position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts.Item.DistrictsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public DistrictsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public DistrictsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Districts/Item/DistrictsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Districts/Item/DistrictsItemRequestBuilder.cs new file mode 100644 index 0000000000..a53f2f111f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Districts/Item/DistrictsItemRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts.Item.Relationships; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts.Item +{ + /// + /// Builds and executes requests for operations under \districts\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class DistrictsItemRequestBuilder : BaseRequestBuilder + { + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public DistrictsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts/{id}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public DistrictsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts/{id}", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Districts/Item/Relationships/Buildings/BuildingsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Districts/Item/Relationships/Buildings/BuildingsRequestBuilder.cs new file mode 100644 index 0000000000..2c763350f3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Districts/Item/Relationships/Buildings/BuildingsRequestBuilder.cs @@ -0,0 +1,248 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts.Item.Relationships.Buildings +{ + /// + /// Builds and executes requests for operations under \districts\{id}\relationships\buildings + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BuildingsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public BuildingsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts/{id}/relationships/buildings{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public BuildingsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts/{id}/relationships/buildings{?query*}", rawUrl) + { + } + + /// + /// Removes existing buildings from the buildings relationship of an individual district. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task DeleteAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyBuildingInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToDeleteRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related building identities of an individual district's buildings relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BuildingIdentifierCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns existing buildings to the buildings relationship of an individual district. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyBuildingInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Adds existing buildings to the buildings relationship of an individual district. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyBuildingInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Removes existing buildings from the buildings relationship of an individual district. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyBuildingInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Retrieves the related building identities of an individual district's buildings relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns existing buildings to the buildings relationship of an individual district. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyBuildingInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Adds existing buildings to the buildings relationship of an individual district. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyBuildingInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts.Item.Relationships.Buildings.BuildingsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts.Item.Relationships.Buildings.BuildingsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related building identities of an individual district's buildings relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BuildingsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BuildingsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Districts/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Districts/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..8fd8f8bd25 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Districts/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,52 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts.Item.Relationships.Buildings; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts.Item.Relationships.Roads; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \districts\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The buildings property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts.Item.Relationships.Buildings.BuildingsRequestBuilder Buildings + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts.Item.Relationships.Buildings.BuildingsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The roads property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts.Item.Relationships.Roads.RoadsRequestBuilder Roads + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts.Item.Relationships.Roads.RoadsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Districts/Item/Relationships/Roads/RoadsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Districts/Item/Relationships/Roads/RoadsRequestBuilder.cs new file mode 100644 index 0000000000..327ff7860a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Districts/Item/Relationships/Roads/RoadsRequestBuilder.cs @@ -0,0 +1,248 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts.Item.Relationships.Roads +{ + /// + /// Builds and executes requests for operations under \districts\{id}\relationships\roads + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoadsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RoadsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts/{id}/relationships/roads{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RoadsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts/{id}/relationships/roads{?query*}", rawUrl) + { + } + + /// + /// Removes existing roads from the roads relationship of an individual district. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task DeleteAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoadInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToDeleteRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related road identities of an individual district's roads relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoadIdentifierCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns existing roads to the roads relationship of an individual district. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoadInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Adds existing roads to the roads relationship of an individual district. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoadInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Removes existing roads from the roads relationship of an individual district. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoadInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Retrieves the related road identities of an individual district's roads relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns existing roads to the roads relationship of an individual district. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoadInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Adds existing roads to the roads relationship of an individual district. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoadInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts.Item.Relationships.Roads.RoadsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts.Item.Relationships.Roads.RoadsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related road identities of an individual district's roads relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoadsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoadsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/FamilyHomes/FamilyHomesRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/FamilyHomes/FamilyHomesRequestBuilder.cs new file mode 100644 index 0000000000..e9c32fdaff --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/FamilyHomes/FamilyHomesRequestBuilder.cs @@ -0,0 +1,52 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.FamilyHomes.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.FamilyHomes +{ + /// + /// Builds and executes requests for operations under \familyHomes + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class FamilyHomesRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.familyHomes.item collection + /// The identifier of the familyHome whose related room identities to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.FamilyHomes.Item.FamilyHomesItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.FamilyHomes.Item.FamilyHomesItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public FamilyHomesRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public FamilyHomesRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/FamilyHomes/Item/FamilyHomesItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/FamilyHomes/Item/FamilyHomesItemRequestBuilder.cs new file mode 100644 index 0000000000..ed3b04f708 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/FamilyHomes/Item/FamilyHomesItemRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.FamilyHomes.Item.Relationships; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.FamilyHomes.Item +{ + /// + /// Builds and executes requests for operations under \familyHomes\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class FamilyHomesItemRequestBuilder : BaseRequestBuilder + { + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.FamilyHomes.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.FamilyHomes.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public FamilyHomesItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes/{id}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public FamilyHomesItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes/{id}", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/FamilyHomes/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/FamilyHomes/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..b444317972 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/FamilyHomes/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.FamilyHomes.Item.Relationships.Rooms; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.FamilyHomes.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \familyHomes\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The rooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.FamilyHomes.Item.Relationships.Rooms.RoomsRequestBuilder Rooms + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.FamilyHomes.Item.Relationships.Rooms.RoomsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/FamilyHomes/Item/Relationships/Rooms/RoomsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/FamilyHomes/Item/Relationships/Rooms/RoomsRequestBuilder.cs new file mode 100644 index 0000000000..5db68f23c8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/FamilyHomes/Item/Relationships/Rooms/RoomsRequestBuilder.cs @@ -0,0 +1,248 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.FamilyHomes.Item.Relationships.Rooms +{ + /// + /// Builds and executes requests for operations under \familyHomes\{id}\relationships\rooms + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes/{id}/relationships/rooms{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes/{id}/relationships/rooms{?query*}", rawUrl) + { + } + + /// + /// Removes existing rooms from the rooms relationship of an individual familyHome. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task DeleteAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToDeleteRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related room identities of an individual familyHome's rooms relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns existing rooms to the rooms relationship of an individual familyHome. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Adds existing rooms to the rooms relationship of an individual familyHome. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Removes existing rooms from the rooms relationship of an individual familyHome. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Retrieves the related room identities of an individual familyHome's rooms relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns existing rooms to the rooms relationship of an individual familyHome. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Adds existing rooms to the rooms relationship of an individual familyHome. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.FamilyHomes.Item.Relationships.Rooms.RoomsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.FamilyHomes.Item.Relationships.Rooms.RoomsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related room identities of an individual familyHome's rooms relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Kitchens/Item/KitchensItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Kitchens/Item/KitchensItemRequestBuilder.cs new file mode 100644 index 0000000000..24db678ff1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Kitchens/Item/KitchensItemRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Kitchens.Item.Relationships; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Kitchens.Item +{ + /// + /// Builds and executes requests for operations under \kitchens\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class KitchensItemRequestBuilder : BaseRequestBuilder + { + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Kitchens.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Kitchens.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public KitchensItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/kitchens/{id}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public KitchensItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/kitchens/{id}", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Kitchens/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Kitchens/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..aad4c41847 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Kitchens/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Kitchens.Item.Relationships.Residence; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Kitchens.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \kitchens\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Kitchens.Item.Relationships.Residence.ResidenceRequestBuilder Residence + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Kitchens.Item.Relationships.Residence.ResidenceRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/kitchens/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/kitchens/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Kitchens/Item/Relationships/Residence/ResidenceRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Kitchens/Item/Relationships/Residence/ResidenceRequestBuilder.cs new file mode 100644 index 0000000000..64e2187053 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Kitchens/Item/Relationships/Residence/ResidenceRequestBuilder.cs @@ -0,0 +1,168 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Kitchens.Item.Relationships.Residence +{ + /// + /// Builds and executes requests for operations under \kitchens\{id}\relationships\residence + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/kitchens/{id}/relationships/residence{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/kitchens/{id}/relationships/residence{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related residence identity of an individual kitchen's residence relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns an existing residence to the residence relationship of an individual kitchen. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related residence identity of an individual kitchen's residence relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns an existing residence to the residence relationship of an individual kitchen. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Kitchens.Item.Relationships.Residence.ResidenceRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Kitchens.Item.Relationships.Residence.ResidenceRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related residence identity of an individual kitchen's residence relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Kitchens/KitchensRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Kitchens/KitchensRequestBuilder.cs new file mode 100644 index 0000000000..e7bc03280b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Kitchens/KitchensRequestBuilder.cs @@ -0,0 +1,52 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Kitchens.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Kitchens +{ + /// + /// Builds and executes requests for operations under \kitchens + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class KitchensRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.kitchens.item collection + /// The identifier of the kitchen whose related residence identity to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Kitchens.Item.KitchensItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Kitchens.Item.KitchensItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public KitchensRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/kitchens", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public KitchensRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/kitchens", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/LivingRooms/Item/LivingRoomsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/LivingRooms/Item/LivingRoomsItemRequestBuilder.cs new file mode 100644 index 0000000000..c2e63940f7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/LivingRooms/Item/LivingRoomsItemRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.LivingRooms.Item.Relationships; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.LivingRooms.Item +{ + /// + /// Builds and executes requests for operations under \livingRooms\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class LivingRoomsItemRequestBuilder : BaseRequestBuilder + { + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.LivingRooms.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.LivingRooms.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public LivingRoomsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/livingRooms/{id}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public LivingRoomsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/livingRooms/{id}", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/LivingRooms/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/LivingRooms/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..a5a20b15ce --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/LivingRooms/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.LivingRooms.Item.Relationships.Residence; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.LivingRooms.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \livingRooms\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.LivingRooms.Item.Relationships.Residence.ResidenceRequestBuilder Residence + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.LivingRooms.Item.Relationships.Residence.ResidenceRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/livingRooms/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/livingRooms/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/LivingRooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/LivingRooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs new file mode 100644 index 0000000000..b93d8e89f8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/LivingRooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs @@ -0,0 +1,168 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.LivingRooms.Item.Relationships.Residence +{ + /// + /// Builds and executes requests for operations under \livingRooms\{id}\relationships\residence + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/livingRooms/{id}/relationships/residence{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/livingRooms/{id}/relationships/residence{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related residence identity of an individual livingRoom's residence relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns an existing residence to the residence relationship of an individual livingRoom. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related residence identity of an individual livingRoom's residence relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns an existing residence to the residence relationship of an individual livingRoom. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.LivingRooms.Item.Relationships.Residence.ResidenceRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.LivingRooms.Item.Relationships.Residence.ResidenceRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related residence identity of an individual livingRoom's residence relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/LivingRooms/LivingRoomsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/LivingRooms/LivingRoomsRequestBuilder.cs new file mode 100644 index 0000000000..3df6c70421 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/LivingRooms/LivingRoomsRequestBuilder.cs @@ -0,0 +1,52 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.LivingRooms.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.LivingRooms +{ + /// + /// Builds and executes requests for operations under \livingRooms + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class LivingRoomsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.livingRooms.item collection + /// The identifier of the livingRoom whose related residence identity to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.LivingRooms.Item.LivingRoomsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.LivingRooms.Item.LivingRoomsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public LivingRoomsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/livingRooms", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public LivingRoomsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/livingRooms", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Mansions/Item/MansionsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Mansions/Item/MansionsItemRequestBuilder.cs new file mode 100644 index 0000000000..e28ea4f657 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Mansions/Item/MansionsItemRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions.Item.Relationships; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions.Item +{ + /// + /// Builds and executes requests for operations under \mansions\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class MansionsItemRequestBuilder : BaseRequestBuilder + { + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public MansionsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions/{id}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public MansionsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions/{id}", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Mansions/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Mansions/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..d1ae8eb805 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Mansions/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,52 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions.Item.Relationships.Rooms; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions.Item.Relationships.Staff; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \mansions\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The rooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions.Item.Relationships.Rooms.RoomsRequestBuilder Rooms + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions.Item.Relationships.Rooms.RoomsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The staff property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions.Item.Relationships.Staff.StaffRequestBuilder Staff + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions.Item.Relationships.Staff.StaffRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Mansions/Item/Relationships/Rooms/RoomsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Mansions/Item/Relationships/Rooms/RoomsRequestBuilder.cs new file mode 100644 index 0000000000..8559c1e418 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Mansions/Item/Relationships/Rooms/RoomsRequestBuilder.cs @@ -0,0 +1,248 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions.Item.Relationships.Rooms +{ + /// + /// Builds and executes requests for operations under \mansions\{id}\relationships\rooms + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions/{id}/relationships/rooms{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions/{id}/relationships/rooms{?query*}", rawUrl) + { + } + + /// + /// Removes existing rooms from the rooms relationship of an individual mansion. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task DeleteAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToDeleteRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related room identities of an individual mansion's rooms relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns existing rooms to the rooms relationship of an individual mansion. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Adds existing rooms to the rooms relationship of an individual mansion. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Removes existing rooms from the rooms relationship of an individual mansion. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Retrieves the related room identities of an individual mansion's rooms relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns existing rooms to the rooms relationship of an individual mansion. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Adds existing rooms to the rooms relationship of an individual mansion. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions.Item.Relationships.Rooms.RoomsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions.Item.Relationships.Rooms.RoomsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related room identities of an individual mansion's rooms relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Mansions/Item/Relationships/Staff/StaffRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Mansions/Item/Relationships/Staff/StaffRequestBuilder.cs new file mode 100644 index 0000000000..f311818aac --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Mansions/Item/Relationships/Staff/StaffRequestBuilder.cs @@ -0,0 +1,248 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions.Item.Relationships.Staff +{ + /// + /// Builds and executes requests for operations under \mansions\{id}\relationships\staff + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class StaffRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public StaffRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions/{id}/relationships/staff{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public StaffRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions/{id}/relationships/staff{?query*}", rawUrl) + { + } + + /// + /// Removes existing staffMembers from the staff relationship of an individual mansion. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task DeleteAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyStaffMemberInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToDeleteRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related staffMember identities of an individual mansion's staff relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.StaffMemberIdentifierCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns existing staffMembers to the staff relationship of an individual mansion. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyStaffMemberInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Adds existing staffMembers to the staff relationship of an individual mansion. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyStaffMemberInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Removes existing staffMembers from the staff relationship of an individual mansion. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyStaffMemberInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Retrieves the related staffMember identities of an individual mansion's staff relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns existing staffMembers to the staff relationship of an individual mansion. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyStaffMemberInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Adds existing staffMembers to the staff relationship of an individual mansion. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyStaffMemberInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions.Item.Relationships.Staff.StaffRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions.Item.Relationships.Staff.StaffRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related staffMember identities of an individual mansion's staff relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class StaffRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class StaffRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Mansions/MansionsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Mansions/MansionsRequestBuilder.cs new file mode 100644 index 0000000000..96bb107cec --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Mansions/MansionsRequestBuilder.cs @@ -0,0 +1,52 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions +{ + /// + /// Builds and executes requests for operations under \mansions + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class MansionsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.mansions.item collection + /// The identifier of the mansion whose related room identities to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions.Item.MansionsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions.Item.MansionsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public MansionsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public MansionsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/mansions", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AddOperationCode.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AddOperationCode.cs new file mode 100644 index 0000000000..0e9bbb9331 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AddOperationCode.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum AddOperationCode + #pragma warning restore CS1591 + { + [EnumMember(Value = "add")] + #pragma warning disable CS1591 + Add, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AddToDistrictBuildingsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AddToDistrictBuildingsRelationshipOperation.cs new file mode 100644 index 0000000000..4143782e3b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AddToDistrictBuildingsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AddToDistrictBuildingsRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.DistrictBuildingsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddToDistrictBuildingsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddToDistrictBuildingsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BuildingIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.DistrictBuildingsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AddToDistrictRoadsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AddToDistrictRoadsRelationshipOperation.cs new file mode 100644 index 0000000000..491c7bb12c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AddToDistrictRoadsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AddToDistrictRoadsRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.DistrictRoadsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddToDistrictRoadsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddToDistrictRoadsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoadIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.DistrictRoadsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AddToFamilyHomeRoomsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AddToFamilyHomeRoomsRelationshipOperation.cs new file mode 100644 index 0000000000..2bcd6624a6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AddToFamilyHomeRoomsRelationshipOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AddToFamilyHomeRoomsRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddToResidenceRoomsRelationshipOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddToFamilyHomeRoomsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddToFamilyHomeRoomsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AddToMansionRoomsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AddToMansionRoomsRelationshipOperation.cs new file mode 100644 index 0000000000..799fc718e2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AddToMansionRoomsRelationshipOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AddToMansionRoomsRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddToResidenceRoomsRelationshipOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddToMansionRoomsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddToMansionRoomsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AddToMansionStaffRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AddToMansionStaffRelationshipOperation.cs new file mode 100644 index 0000000000..763e97fd5b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AddToMansionStaffRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AddToMansionStaffRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.MansionStaffRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddToMansionStaffRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddToMansionStaffRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.StaffMemberIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.MansionStaffRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AddToResidenceRoomsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AddToResidenceRoomsRelationshipOperation.cs new file mode 100644 index 0000000000..ca2267c9e0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AddToResidenceRoomsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AddToResidenceRoomsRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceRoomsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddToResidenceRoomsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddToResidenceRoomsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceRoomsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AtomicOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AtomicOperation.cs new file mode 100644 index 0000000000..febb9386bc --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AtomicOperation.cs @@ -0,0 +1,107 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AtomicOperation : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The openapiDiscriminator property + public string? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AtomicOperation() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AtomicOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "addToDistrictBuildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddToDistrictBuildingsRelationshipOperation(), + "addToDistrictRoads" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddToDistrictRoadsRelationshipOperation(), + "addToFamilyHomeRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddToFamilyHomeRoomsRelationshipOperation(), + "addToMansionRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddToMansionRoomsRelationshipOperation(), + "addToMansionStaff" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddToMansionStaffRelationshipOperation(), + "addToResidenceRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AddToResidenceRoomsRelationshipOperation(), + "removeFromDistrictBuildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveFromDistrictBuildingsRelationshipOperation(), + "removeFromDistrictRoads" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveFromDistrictRoadsRelationshipOperation(), + "removeFromFamilyHomeRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveFromFamilyHomeRoomsRelationshipOperation(), + "removeFromMansionRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveFromMansionRoomsRelationshipOperation(), + "removeFromMansionStaff" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveFromMansionStaffRelationshipOperation(), + "removeFromResidenceRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveFromResidenceRoomsRelationshipOperation(), + "updateBathroomResidence" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateBathroomResidenceRelationshipOperation(), + "updateBedroomResidence" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateBedroomResidenceRelationshipOperation(), + "updateDistrictBuildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateDistrictBuildingsRelationshipOperation(), + "updateDistrictRoads" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateDistrictRoadsRelationshipOperation(), + "updateFamilyHomeRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateFamilyHomeRoomsRelationshipOperation(), + "updateKitchenResidence" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateKitchenResidenceRelationshipOperation(), + "updateLivingRoomResidence" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateLivingRoomResidenceRelationshipOperation(), + "updateMansionRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateMansionRoomsRelationshipOperation(), + "updateMansionStaff" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateMansionStaffRelationshipOperation(), + "updateResidenceRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateResidenceRoomsRelationshipOperation(), + "updateRoomResidence" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateRoomResidenceRelationshipOperation(), + "updateToiletResidence" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateToiletResidenceRelationshipOperation(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AtomicOperation(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteStringValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AtomicResult.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AtomicResult.cs new file mode 100644 index 0000000000..7300ca2577 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/AtomicResult.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AtomicResult : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AtomicResult() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AtomicResult CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AtomicResult(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BathroomIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BathroomIdentifierInRequest.cs new file mode 100644 index 0000000000..c30522c543 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BathroomIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BathroomIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BathroomIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BathroomIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BathroomIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BathroomIdentifierInResponse.cs new file mode 100644 index 0000000000..9c60fb2434 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BathroomIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BathroomIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BathroomIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BathroomIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BedroomIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BedroomIdentifierInRequest.cs new file mode 100644 index 0000000000..bed3610a61 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BedroomIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BedroomIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BedroomIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BedroomIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BedroomIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BedroomIdentifierInResponse.cs new file mode 100644 index 0000000000..fc32f3a944 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BedroomIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BedroomIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BedroomIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BedroomIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BuildingIdentifierCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BuildingIdentifierCollectionResponseDocument.cs new file mode 100644 index 0000000000..aacdc4d995 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BuildingIdentifierCollectionResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BuildingIdentifierCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public BuildingIdentifierCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BuildingIdentifierCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BuildingIdentifierCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BuildingIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BuildingIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BuildingIdentifierInRequest.cs new file mode 100644 index 0000000000..406132dd44 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BuildingIdentifierInRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BuildingIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BuildingIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BuildingIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BuildingIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BuildingIdentifierInResponse.cs new file mode 100644 index 0000000000..e00c377eb1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BuildingIdentifierInResponse.cs @@ -0,0 +1,95 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BuildingIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BuildingResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public BuildingIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BuildingIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.FamilyHomeIdentifierInResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.MansionIdentifierInResponse(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierInResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BuildingIdentifierInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BuildingResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BuildingResourceType.cs new file mode 100644 index 0000000000..a90cdecac6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/BuildingResourceType.cs @@ -0,0 +1,26 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum BuildingResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "familyHomes")] + #pragma warning disable CS1591 + FamilyHomes, + #pragma warning restore CS1591 + [EnumMember(Value = "mansions")] + #pragma warning disable CS1591 + Mansions, + #pragma warning restore CS1591 + [EnumMember(Value = "residences")] + #pragma warning disable CS1591 + Residences, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/CyclePathIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/CyclePathIdentifierInRequest.cs new file mode 100644 index 0000000000..ebcb35eabe --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/CyclePathIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CyclePathIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoadIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.CyclePathIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.CyclePathIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/CyclePathIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/CyclePathIdentifierInResponse.cs new file mode 100644 index 0000000000..4d1a6ba08c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/CyclePathIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CyclePathIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoadIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.CyclePathIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.CyclePathIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/DistrictBuildingsRelationshipIdentifier.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/DistrictBuildingsRelationshipIdentifier.cs new file mode 100644 index 0000000000..477bc183b3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/DistrictBuildingsRelationshipIdentifier.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DistrictBuildingsRelationshipIdentifier : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationship property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.DistrictBuildingsRelationshipName? Relationship + { + get { return BackingStore?.Get("relationship"); } + set { BackingStore?.Set("relationship", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.DistrictResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public DistrictBuildingsRelationshipIdentifier() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.DistrictBuildingsRelationshipIdentifier CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.DistrictBuildingsRelationshipIdentifier(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetGuidValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationship", n => { Relationship = n.GetEnumValue(); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteGuidValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteEnumValue("relationship", Relationship); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/DistrictBuildingsRelationshipName.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/DistrictBuildingsRelationshipName.cs new file mode 100644 index 0000000000..40b7f00d41 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/DistrictBuildingsRelationshipName.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum DistrictBuildingsRelationshipName + #pragma warning restore CS1591 + { + [EnumMember(Value = "buildings")] + #pragma warning disable CS1591 + Buildings, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/DistrictResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/DistrictResourceType.cs new file mode 100644 index 0000000000..15cf98cad9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/DistrictResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum DistrictResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "districts")] + #pragma warning disable CS1591 + Districts, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/DistrictRoadsRelationshipIdentifier.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/DistrictRoadsRelationshipIdentifier.cs new file mode 100644 index 0000000000..bdc96f78bb --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/DistrictRoadsRelationshipIdentifier.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DistrictRoadsRelationshipIdentifier : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationship property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.DistrictRoadsRelationshipName? Relationship + { + get { return BackingStore?.Get("relationship"); } + set { BackingStore?.Set("relationship", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.DistrictResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public DistrictRoadsRelationshipIdentifier() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.DistrictRoadsRelationshipIdentifier CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.DistrictRoadsRelationshipIdentifier(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetGuidValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationship", n => { Relationship = n.GetEnumValue(); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteGuidValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteEnumValue("relationship", Relationship); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/DistrictRoadsRelationshipName.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/DistrictRoadsRelationshipName.cs new file mode 100644 index 0000000000..f81f345607 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/DistrictRoadsRelationshipName.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum DistrictRoadsRelationshipName + #pragma warning restore CS1591 + { + [EnumMember(Value = "roads")] + #pragma warning disable CS1591 + Roads, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ErrorLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ErrorLinks.cs new file mode 100644 index 0000000000..a992df3506 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ErrorLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// The about property + public string? About + { + get { return BackingStore?.Get("about"); } + set { BackingStore?.Set("about", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The type property + public string? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "about", n => { About = n.GetStringValue(); } }, + { "type", n => { Type = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("about", About); + writer.WriteStringValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ErrorObject.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ErrorObject.cs new file mode 100644 index 0000000000..27e8c66e17 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ErrorObject.cs @@ -0,0 +1,133 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorObject : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The code property + public string? Code + { + get { return BackingStore?.Get("code"); } + set { BackingStore?.Set("code", value); } + } + + /// The detail property + public string? Detail + { + get { return BackingStore?.Get("detail"); } + set { BackingStore?.Set("detail", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The source property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorSource? Source + { + get { return BackingStore?.Get("source"); } + set { BackingStore?.Set("source", value); } + } + + /// The status property + public string? Status + { + get { return BackingStore?.Get("status"); } + set { BackingStore?.Set("status", value); } + } + + /// The title property + public string? Title + { + get { return BackingStore?.Get("title"); } + set { BackingStore?.Set("title", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorObject() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorObject CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorObject(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "code", n => { Code = n.GetStringValue(); } }, + { "detail", n => { Detail = n.GetStringValue(); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "source", n => { Source = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorSource.CreateFromDiscriminatorValue); } }, + { "status", n => { Status = n.GetStringValue(); } }, + { "title", n => { Title = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("code", Code); + writer.WriteStringValue("detail", Detail); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + writer.WriteObjectValue("source", Source); + writer.WriteStringValue("status", Status); + writer.WriteStringValue("title", Title); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ErrorResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ErrorResponseDocument.cs new file mode 100644 index 0000000000..6d1af3228b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ErrorResponseDocument.cs @@ -0,0 +1,92 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorResponseDocument : ApiException, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The errors property + public List? Errors + { + get { return BackingStore?.Get?>("errors"); } + set { BackingStore?.Set("errors", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The primary error message. + public override string Message { get => base.Message; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "errors", n => { Errors = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorObject.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("errors", Errors); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ErrorSource.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ErrorSource.cs new file mode 100644 index 0000000000..c14aa4fb5f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ErrorSource.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorSource : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The header property + public string? Header + { + get { return BackingStore?.Get("header"); } + set { BackingStore?.Set("header", value); } + } + + /// The parameter property + public string? Parameter + { + get { return BackingStore?.Get("parameter"); } + set { BackingStore?.Set("parameter", value); } + } + + /// The pointer property + public string? Pointer + { + get { return BackingStore?.Get("pointer"); } + set { BackingStore?.Set("pointer", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorSource() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorSource CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorSource(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "header", n => { Header = n.GetStringValue(); } }, + { "parameter", n => { Parameter = n.GetStringValue(); } }, + { "pointer", n => { Pointer = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("header", Header); + writer.WriteStringValue("parameter", Parameter); + writer.WriteStringValue("pointer", Pointer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ErrorTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ErrorTopLevelLinks.cs new file mode 100644 index 0000000000..250b544f85 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ErrorTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/FamilyHomeIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/FamilyHomeIdentifierInRequest.cs new file mode 100644 index 0000000000..26ec985023 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/FamilyHomeIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class FamilyHomeIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.FamilyHomeIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.FamilyHomeIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/FamilyHomeIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/FamilyHomeIdentifierInResponse.cs new file mode 100644 index 0000000000..829e6af19c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/FamilyHomeIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class FamilyHomeIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.FamilyHomeIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.FamilyHomeIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/IdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/IdentifierInRequest.cs new file mode 100644 index 0000000000..154dcaf1b6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/IdentifierInRequest.cs @@ -0,0 +1,96 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class IdentifierInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public IdentifierInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.IdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BathroomIdentifierInRequest(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BedroomIdentifierInRequest(), + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BuildingIdentifierInRequest(), + "cyclePaths" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.CyclePathIdentifierInRequest(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.FamilyHomeIdentifierInRequest(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.KitchenIdentifierInRequest(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.LivingRoomIdentifierInRequest(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.MansionIdentifierInRequest(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierInRequest(), + "roads" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoadIdentifierInRequest(), + "rooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierInRequest(), + "staffMembers" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.StaffMemberIdentifierInRequest(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToiletIdentifierInRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.IdentifierInRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/KitchenIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/KitchenIdentifierInRequest.cs new file mode 100644 index 0000000000..29aa2132d6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/KitchenIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class KitchenIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.KitchenIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.KitchenIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/KitchenIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/KitchenIdentifierInResponse.cs new file mode 100644 index 0000000000..0898c1303c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/KitchenIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class KitchenIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.KitchenIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.KitchenIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/LivingRoomIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/LivingRoomIdentifierInRequest.cs new file mode 100644 index 0000000000..3441c0b18b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/LivingRoomIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class LivingRoomIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.LivingRoomIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.LivingRoomIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/LivingRoomIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/LivingRoomIdentifierInResponse.cs new file mode 100644 index 0000000000..85f205b62c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/LivingRoomIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class LivingRoomIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.LivingRoomIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.LivingRoomIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/MansionIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/MansionIdentifierInRequest.cs new file mode 100644 index 0000000000..4d98aeb73b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/MansionIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class MansionIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.MansionIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.MansionIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/MansionIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/MansionIdentifierInResponse.cs new file mode 100644 index 0000000000..fbd0850f8f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/MansionIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class MansionIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.MansionIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.MansionIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/MansionResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/MansionResourceType.cs new file mode 100644 index 0000000000..487c9d3324 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/MansionResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum MansionResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "mansions")] + #pragma warning disable CS1591 + Mansions, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/MansionStaffRelationshipIdentifier.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/MansionStaffRelationshipIdentifier.cs new file mode 100644 index 0000000000..427641c710 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/MansionStaffRelationshipIdentifier.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class MansionStaffRelationshipIdentifier : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationship property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.MansionStaffRelationshipName? Relationship + { + get { return BackingStore?.Get("relationship"); } + set { BackingStore?.Set("relationship", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.MansionResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public MansionStaffRelationshipIdentifier() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.MansionStaffRelationshipIdentifier CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.MansionStaffRelationshipIdentifier(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationship", n => { Relationship = n.GetEnumValue(); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteEnumValue("relationship", Relationship); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/MansionStaffRelationshipName.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/MansionStaffRelationshipName.cs new file mode 100644 index 0000000000..77cb0a08fa --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/MansionStaffRelationshipName.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum MansionStaffRelationshipName + #pragma warning restore CS1591 + { + [EnumMember(Value = "staff")] + #pragma warning disable CS1591 + Staff, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/Meta.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/Meta.cs new file mode 100644 index 0000000000..6e0ac0995e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/Meta.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class Meta : IAdditionalDataHolder, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + public IDictionary AdditionalData + { + get { return BackingStore.Get>("AdditionalData") ?? new Dictionary(); } + set { BackingStore.Set("AdditionalData", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// + /// Instantiates a new and sets the default values. + /// + public Meta() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + AdditionalData = new Dictionary(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteAdditionalData(AdditionalData); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/OperationsRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/OperationsRequestDocument.cs new file mode 100644 index 0000000000..a2dc93bcd8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/OperationsRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class OperationsRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// The atomicOperations property + public List? AtomicOperations + { + get { return BackingStore?.Get?>("atomic:operations"); } + set { BackingStore?.Set("atomic:operations", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public OperationsRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.OperationsRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.OperationsRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "atomic:operations", n => { AtomicOperations = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AtomicOperation.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("atomic:operations", AtomicOperations); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/OperationsResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/OperationsResponseDocument.cs new file mode 100644 index 0000000000..3b5d5fed63 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/OperationsResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class OperationsResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// The atomicResults property + public List? AtomicResults + { + get { return BackingStore?.Get?>("atomic:results"); } + set { BackingStore?.Set("atomic:results", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public OperationsResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.OperationsResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.OperationsResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "atomic:results", n => { AtomicResults = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AtomicResult.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("atomic:results", AtomicResults); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RemoveFromDistrictBuildingsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RemoveFromDistrictBuildingsRelationshipOperation.cs new file mode 100644 index 0000000000..7550cf1801 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RemoveFromDistrictBuildingsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RemoveFromDistrictBuildingsRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.DistrictBuildingsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveFromDistrictBuildingsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveFromDistrictBuildingsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BuildingIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.DistrictBuildingsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RemoveFromDistrictRoadsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RemoveFromDistrictRoadsRelationshipOperation.cs new file mode 100644 index 0000000000..0b8f61cd81 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RemoveFromDistrictRoadsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RemoveFromDistrictRoadsRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.DistrictRoadsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveFromDistrictRoadsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveFromDistrictRoadsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoadIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.DistrictRoadsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RemoveFromFamilyHomeRoomsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RemoveFromFamilyHomeRoomsRelationshipOperation.cs new file mode 100644 index 0000000000..6b48a1b594 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RemoveFromFamilyHomeRoomsRelationshipOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RemoveFromFamilyHomeRoomsRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveFromResidenceRoomsRelationshipOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveFromFamilyHomeRoomsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveFromFamilyHomeRoomsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RemoveFromMansionRoomsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RemoveFromMansionRoomsRelationshipOperation.cs new file mode 100644 index 0000000000..325180cab0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RemoveFromMansionRoomsRelationshipOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RemoveFromMansionRoomsRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveFromResidenceRoomsRelationshipOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveFromMansionRoomsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveFromMansionRoomsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RemoveFromMansionStaffRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RemoveFromMansionStaffRelationshipOperation.cs new file mode 100644 index 0000000000..6a93441877 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RemoveFromMansionStaffRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RemoveFromMansionStaffRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.MansionStaffRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveFromMansionStaffRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveFromMansionStaffRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.StaffMemberIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.MansionStaffRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RemoveFromResidenceRoomsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RemoveFromResidenceRoomsRelationshipOperation.cs new file mode 100644 index 0000000000..a095c7e1c6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RemoveFromResidenceRoomsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RemoveFromResidenceRoomsRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceRoomsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveFromResidenceRoomsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RemoveFromResidenceRoomsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceRoomsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RemoveOperationCode.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RemoveOperationCode.cs new file mode 100644 index 0000000000..fdce79bec1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RemoveOperationCode.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum RemoveOperationCode + #pragma warning restore CS1591 + { + [EnumMember(Value = "remove")] + #pragma warning disable CS1591 + Remove, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResidenceIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResidenceIdentifierInRequest.cs new file mode 100644 index 0000000000..4c9355ec83 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResidenceIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResidenceIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BuildingIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResidenceIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResidenceIdentifierInResponse.cs new file mode 100644 index 0000000000..a35c6f3285 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResidenceIdentifierInResponse.cs @@ -0,0 +1,56 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResidenceIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BuildingIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.FamilyHomeIdentifierInResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.MansionIdentifierInResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResidenceIdentifierResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResidenceIdentifierResponseDocument.cs new file mode 100644 index 0000000000..adb0c6d282 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResidenceIdentifierResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResidenceIdentifierResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceIdentifierTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResidenceIdentifierResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceIdentifierTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResidenceResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResidenceResourceType.cs new file mode 100644 index 0000000000..c22582634f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResidenceResourceType.cs @@ -0,0 +1,26 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum ResidenceResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "familyHomes")] + #pragma warning disable CS1591 + FamilyHomes, + #pragma warning restore CS1591 + [EnumMember(Value = "mansions")] + #pragma warning disable CS1591 + Mansions, + #pragma warning restore CS1591 + [EnumMember(Value = "residences")] + #pragma warning disable CS1591 + Residences, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResidenceRoomsRelationshipIdentifier.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResidenceRoomsRelationshipIdentifier.cs new file mode 100644 index 0000000000..8fdf5a9cc5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResidenceRoomsRelationshipIdentifier.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResidenceRoomsRelationshipIdentifier : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationship property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceRoomsRelationshipName? Relationship + { + get { return BackingStore?.Get("relationship"); } + set { BackingStore?.Set("relationship", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResidenceRoomsRelationshipIdentifier() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceRoomsRelationshipIdentifier CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceRoomsRelationshipIdentifier(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationship", n => { Relationship = n.GetEnumValue(); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteEnumValue("relationship", Relationship); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResidenceRoomsRelationshipName.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResidenceRoomsRelationshipName.cs new file mode 100644 index 0000000000..b3d503202b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResidenceRoomsRelationshipName.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum ResidenceRoomsRelationshipName + #pragma warning restore CS1591 + { + [EnumMember(Value = "rooms")] + #pragma warning disable CS1591 + Rooms, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs new file mode 100644 index 0000000000..591118db9b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs @@ -0,0 +1,124 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceIdentifierCollectionTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The first property + public string? First + { + get { return BackingStore?.Get("first"); } + set { BackingStore?.Set("first", value); } + } + + /// The last property + public string? Last + { + get { return BackingStore?.Get("last"); } + set { BackingStore?.Set("last", value); } + } + + /// The next property + public string? Next + { + get { return BackingStore?.Get("next"); } + set { BackingStore?.Set("next", value); } + } + + /// The prev property + public string? Prev + { + get { return BackingStore?.Get("prev"); } + set { BackingStore?.Set("prev", value); } + } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceIdentifierCollectionTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "first", n => { First = n.GetStringValue(); } }, + { "last", n => { Last = n.GetStringValue(); } }, + { "next", n => { Next = n.GetStringValue(); } }, + { "prev", n => { Prev = n.GetStringValue(); } }, + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("first", First); + writer.WriteStringValue("last", Last); + writer.WriteStringValue("next", Next); + writer.WriteStringValue("prev", Prev); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResourceIdentifierTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResourceIdentifierTopLevelLinks.cs new file mode 100644 index 0000000000..65fc63a1ec --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResourceIdentifierTopLevelLinks.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceIdentifierTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceIdentifierTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceIdentifierTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceIdentifierTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResourceInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResourceInResponse.cs new file mode 100644 index 0000000000..90666b96d8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResourceInResponse.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResourceTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResourceTopLevelLinks.cs new file mode 100644 index 0000000000..a9100614f6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResourceTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResourceType.cs new file mode 100644 index 0000000000..d2a7100a24 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ResourceType.cs @@ -0,0 +1,66 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum ResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "bathrooms")] + #pragma warning disable CS1591 + Bathrooms, + #pragma warning restore CS1591 + [EnumMember(Value = "bedrooms")] + #pragma warning disable CS1591 + Bedrooms, + #pragma warning restore CS1591 + [EnumMember(Value = "buildings")] + #pragma warning disable CS1591 + Buildings, + #pragma warning restore CS1591 + [EnumMember(Value = "cyclePaths")] + #pragma warning disable CS1591 + CyclePaths, + #pragma warning restore CS1591 + [EnumMember(Value = "familyHomes")] + #pragma warning disable CS1591 + FamilyHomes, + #pragma warning restore CS1591 + [EnumMember(Value = "kitchens")] + #pragma warning disable CS1591 + Kitchens, + #pragma warning restore CS1591 + [EnumMember(Value = "livingRooms")] + #pragma warning disable CS1591 + LivingRooms, + #pragma warning restore CS1591 + [EnumMember(Value = "mansions")] + #pragma warning disable CS1591 + Mansions, + #pragma warning restore CS1591 + [EnumMember(Value = "residences")] + #pragma warning disable CS1591 + Residences, + #pragma warning restore CS1591 + [EnumMember(Value = "roads")] + #pragma warning disable CS1591 + Roads, + #pragma warning restore CS1591 + [EnumMember(Value = "rooms")] + #pragma warning disable CS1591 + Rooms, + #pragma warning restore CS1591 + [EnumMember(Value = "staffMembers")] + #pragma warning disable CS1591 + StaffMembers, + #pragma warning restore CS1591 + [EnumMember(Value = "toilets")] + #pragma warning disable CS1591 + Toilets, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoadIdentifierCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoadIdentifierCollectionResponseDocument.cs new file mode 100644 index 0000000000..c86d306da9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoadIdentifierCollectionResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RoadIdentifierCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RoadIdentifierCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoadIdentifierCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoadIdentifierCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoadIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoadIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoadIdentifierInRequest.cs new file mode 100644 index 0000000000..c9aba1bf9f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoadIdentifierInRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RoadIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoadIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoadIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoadIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoadIdentifierInResponse.cs new file mode 100644 index 0000000000..2ecbd9c590 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoadIdentifierInResponse.cs @@ -0,0 +1,93 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RoadIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoadResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RoadIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoadIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "cyclePaths" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.CyclePathIdentifierInResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoadIdentifierInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoadResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoadResourceType.cs new file mode 100644 index 0000000000..29e51bb24a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoadResourceType.cs @@ -0,0 +1,22 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum RoadResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "cyclePaths")] + #pragma warning disable CS1591 + CyclePaths, + #pragma warning restore CS1591 + [EnumMember(Value = "roads")] + #pragma warning disable CS1591 + Roads, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoomIdentifierCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoomIdentifierCollectionResponseDocument.cs new file mode 100644 index 0000000000..0269341a9f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoomIdentifierCollectionResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RoomIdentifierCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RoomIdentifierCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoomIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoomIdentifierInRequest.cs new file mode 100644 index 0000000000..89e413363d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoomIdentifierInRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RoomIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoomIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoomIdentifierInResponse.cs new file mode 100644 index 0000000000..a1dc140ad3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoomIdentifierInResponse.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RoomIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RoomIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BathroomIdentifierInResponse(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BedroomIdentifierInResponse(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.KitchenIdentifierInResponse(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.LivingRoomIdentifierInResponse(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToiletIdentifierInResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoomResidenceRelationshipIdentifier.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoomResidenceRelationshipIdentifier.cs new file mode 100644 index 0000000000..0de8196836 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoomResidenceRelationshipIdentifier.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RoomResidenceRelationshipIdentifier : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationship property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomResidenceRelationshipName? Relationship + { + get { return BackingStore?.Get("relationship"); } + set { BackingStore?.Set("relationship", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RoomResidenceRelationshipIdentifier() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomResidenceRelationshipIdentifier CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomResidenceRelationshipIdentifier(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationship", n => { Relationship = n.GetEnumValue(); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteEnumValue("relationship", Relationship); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoomResidenceRelationshipName.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoomResidenceRelationshipName.cs new file mode 100644 index 0000000000..81c5aee1d4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoomResidenceRelationshipName.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum RoomResidenceRelationshipName + #pragma warning restore CS1591 + { + [EnumMember(Value = "residence")] + #pragma warning disable CS1591 + Residence, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoomResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoomResourceType.cs new file mode 100644 index 0000000000..673a7a2627 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/RoomResourceType.cs @@ -0,0 +1,34 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum RoomResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "bathrooms")] + #pragma warning disable CS1591 + Bathrooms, + #pragma warning restore CS1591 + [EnumMember(Value = "bedrooms")] + #pragma warning disable CS1591 + Bedrooms, + #pragma warning restore CS1591 + [EnumMember(Value = "kitchens")] + #pragma warning disable CS1591 + Kitchens, + #pragma warning restore CS1591 + [EnumMember(Value = "livingRooms")] + #pragma warning disable CS1591 + LivingRooms, + #pragma warning restore CS1591 + [EnumMember(Value = "toilets")] + #pragma warning disable CS1591 + Toilets, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/StaffMemberIdentifierCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/StaffMemberIdentifierCollectionResponseDocument.cs new file mode 100644 index 0000000000..a4fa0cac51 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/StaffMemberIdentifierCollectionResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class StaffMemberIdentifierCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public StaffMemberIdentifierCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.StaffMemberIdentifierCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.StaffMemberIdentifierCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.StaffMemberIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/StaffMemberIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/StaffMemberIdentifierInRequest.cs new file mode 100644 index 0000000000..bdb650701e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/StaffMemberIdentifierInRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class StaffMemberIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.StaffMemberIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.StaffMemberIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/StaffMemberIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/StaffMemberIdentifierInResponse.cs new file mode 100644 index 0000000000..3510ef6d72 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/StaffMemberIdentifierInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class StaffMemberIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.StaffMemberResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public StaffMemberIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.StaffMemberIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.StaffMemberIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/StaffMemberResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/StaffMemberResourceType.cs new file mode 100644 index 0000000000..0bab511da5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/StaffMemberResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum StaffMemberResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "staffMembers")] + #pragma warning disable CS1591 + StaffMembers, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ToManyBuildingInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ToManyBuildingInRequest.cs new file mode 100644 index 0000000000..e92d08b38b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ToManyBuildingInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyBuildingInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyBuildingInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyBuildingInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyBuildingInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BuildingIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ToManyRoadInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ToManyRoadInRequest.cs new file mode 100644 index 0000000000..bc28c2046e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ToManyRoadInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyRoadInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyRoadInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoadInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoadInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoadIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ToManyRoomInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ToManyRoomInRequest.cs new file mode 100644 index 0000000000..6d86a46351 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ToManyRoomInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyRoomInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyRoomInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoomInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoomInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ToManyStaffMemberInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ToManyStaffMemberInRequest.cs new file mode 100644 index 0000000000..f3c2657bb4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ToManyStaffMemberInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyStaffMemberInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyStaffMemberInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyStaffMemberInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyStaffMemberInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.StaffMemberIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ToOneResidenceInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ToOneResidenceInRequest.cs new file mode 100644 index 0000000000..35ec5e1481 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ToOneResidenceInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToOneResidenceInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierInRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToOneResidenceInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToOneResidenceInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToOneResidenceInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierInRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ToiletIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ToiletIdentifierInRequest.cs new file mode 100644 index 0000000000..ef9987c75e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ToiletIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToiletIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToiletIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToiletIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ToiletIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ToiletIdentifierInResponse.cs new file mode 100644 index 0000000000..b2b4b5e49e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/ToiletIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToiletIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToiletIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToiletIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateBathroomResidenceRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateBathroomResidenceRelationshipOperation.cs new file mode 100644 index 0000000000..eba920be53 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateBathroomResidenceRelationshipOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateBathroomResidenceRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateRoomResidenceRelationshipOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateBathroomResidenceRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateBathroomResidenceRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateBedroomResidenceRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateBedroomResidenceRelationshipOperation.cs new file mode 100644 index 0000000000..5a33375f85 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateBedroomResidenceRelationshipOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateBedroomResidenceRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateRoomResidenceRelationshipOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateBedroomResidenceRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateBedroomResidenceRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateDistrictBuildingsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateDistrictBuildingsRelationshipOperation.cs new file mode 100644 index 0000000000..fbffe5563f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateDistrictBuildingsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateDistrictBuildingsRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.DistrictBuildingsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateDistrictBuildingsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateDistrictBuildingsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.BuildingIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.DistrictBuildingsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateDistrictRoadsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateDistrictRoadsRelationshipOperation.cs new file mode 100644 index 0000000000..11ec569385 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateDistrictRoadsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateDistrictRoadsRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.DistrictRoadsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateDistrictRoadsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateDistrictRoadsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoadIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.DistrictRoadsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateFamilyHomeRoomsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateFamilyHomeRoomsRelationshipOperation.cs new file mode 100644 index 0000000000..85d83cd7e1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateFamilyHomeRoomsRelationshipOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateFamilyHomeRoomsRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateResidenceRoomsRelationshipOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateFamilyHomeRoomsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateFamilyHomeRoomsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateKitchenResidenceRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateKitchenResidenceRelationshipOperation.cs new file mode 100644 index 0000000000..4201ad673f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateKitchenResidenceRelationshipOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateKitchenResidenceRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateRoomResidenceRelationshipOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateKitchenResidenceRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateKitchenResidenceRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateLivingRoomResidenceRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateLivingRoomResidenceRelationshipOperation.cs new file mode 100644 index 0000000000..88d038fea0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateLivingRoomResidenceRelationshipOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateLivingRoomResidenceRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateRoomResidenceRelationshipOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateLivingRoomResidenceRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateLivingRoomResidenceRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateMansionRoomsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateMansionRoomsRelationshipOperation.cs new file mode 100644 index 0000000000..3936393248 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateMansionRoomsRelationshipOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateMansionRoomsRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateResidenceRoomsRelationshipOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateMansionRoomsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateMansionRoomsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateMansionStaffRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateMansionStaffRelationshipOperation.cs new file mode 100644 index 0000000000..b90a70b240 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateMansionStaffRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateMansionStaffRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.MansionStaffRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateMansionStaffRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateMansionStaffRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.StaffMemberIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.MansionStaffRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateOperationCode.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateOperationCode.cs new file mode 100644 index 0000000000..0145d31557 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateOperationCode.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum UpdateOperationCode + #pragma warning restore CS1591 + { + [EnumMember(Value = "update")] + #pragma warning disable CS1591 + Update, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateResidenceRoomsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateResidenceRoomsRelationshipOperation.cs new file mode 100644 index 0000000000..9e339cc0e6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateResidenceRoomsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateResidenceRoomsRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceRoomsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateResidenceRoomsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateResidenceRoomsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceRoomsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateRoomResidenceRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateRoomResidenceRelationshipOperation.cs new file mode 100644 index 0000000000..c519144898 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateRoomResidenceRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateRoomResidenceRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierInRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomResidenceRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateRoomResidenceRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateRoomResidenceRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierInRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomResidenceRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateToiletResidenceRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateToiletResidenceRelationshipOperation.cs new file mode 100644 index 0000000000..9d9f1a527f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Models/UpdateToiletResidenceRelationshipOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateToiletResidenceRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateRoomResidenceRelationshipOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateToiletResidenceRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.UpdateToiletResidenceRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/OnlyRelationshipsInheritanceClient.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/OnlyRelationshipsInheritanceClient.cs new file mode 100644 index 0000000000..12057ec348 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/OnlyRelationshipsInheritanceClient.cs @@ -0,0 +1,124 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using Microsoft.Kiota.Serialization.Form; +using Microsoft.Kiota.Serialization.Json; +using Microsoft.Kiota.Serialization.Multipart; +using Microsoft.Kiota.Serialization.Text; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bathrooms; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bedrooms; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.FamilyHomes; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Kitchens; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.LivingRooms; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Operations; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Residences; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Rooms; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Toilets; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode +{ + /// + /// The main entry point of the SDK, exposes the configuration and the fluent API. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OnlyRelationshipsInheritanceClient : BaseRequestBuilder + { + /// The bathrooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bathrooms.BathroomsRequestBuilder Bathrooms + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bathrooms.BathroomsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The bedrooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bedrooms.BedroomsRequestBuilder Bedrooms + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Bedrooms.BedroomsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The districts property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts.DistrictsRequestBuilder Districts + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Districts.DistrictsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The familyHomes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.FamilyHomes.FamilyHomesRequestBuilder FamilyHomes + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.FamilyHomes.FamilyHomesRequestBuilder(PathParameters, RequestAdapter); + } + + /// The kitchens property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Kitchens.KitchensRequestBuilder Kitchens + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Kitchens.KitchensRequestBuilder(PathParameters, RequestAdapter); + } + + /// The livingRooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.LivingRooms.LivingRoomsRequestBuilder LivingRooms + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.LivingRooms.LivingRoomsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The mansions property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions.MansionsRequestBuilder Mansions + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Mansions.MansionsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The operations property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Operations.OperationsRequestBuilder Operations + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Operations.OperationsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The residences property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Residences.ResidencesRequestBuilder Residences + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Residences.ResidencesRequestBuilder(PathParameters, RequestAdapter); + } + + /// The rooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Rooms.RoomsRequestBuilder Rooms + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Rooms.RoomsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The toilets property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Toilets.ToiletsRequestBuilder Toilets + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Toilets.ToiletsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The backing store to use for the models. + /// The request adapter to use to execute the requests. + public OnlyRelationshipsInheritanceClient(IRequestAdapter requestAdapter, IBackingStoreFactory backingStore = default) : base(requestAdapter, "{+baseurl}", new Dictionary()) + { + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + if (string.IsNullOrEmpty(RequestAdapter.BaseUrl)) + { + RequestAdapter.BaseUrl = "http://localhost"; + } + PathParameters.TryAdd("baseurl", RequestAdapter.BaseUrl); + RequestAdapter.EnableBackingStore(backingStore); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Operations/OperationsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Operations/OperationsRequestBuilder.cs new file mode 100644 index 0000000000..7bbb822cfc --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Operations/OperationsRequestBuilder.cs @@ -0,0 +1,94 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Operations +{ + /// + /// Builds and executes requests for operations under \operations + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OperationsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public OperationsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/operations", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public OperationsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/operations", rawUrl) + { + } + + /// + /// Performs multiple mutations in a linear and atomic manner. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.OperationsRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.OperationsResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Performs multiple mutations in a linear and atomic manner. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.OperationsRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=atomic;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=atomic;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Operations.OperationsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Operations.OperationsRequestBuilder(rawUrl, RequestAdapter); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Residences/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Residences/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..ca1fbcf640 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Residences/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Residences.Item.Relationships.Rooms; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Residences.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \residences\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The rooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Residences.Item.Relationships.Rooms.RoomsRequestBuilder Rooms + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Residences.Item.Relationships.Rooms.RoomsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/residences/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/residences/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Residences/Item/Relationships/Rooms/RoomsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Residences/Item/Relationships/Rooms/RoomsRequestBuilder.cs new file mode 100644 index 0000000000..4791a55075 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Residences/Item/Relationships/Rooms/RoomsRequestBuilder.cs @@ -0,0 +1,248 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Residences.Item.Relationships.Rooms +{ + /// + /// Builds and executes requests for operations under \residences\{id}\relationships\rooms + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/residences/{id}/relationships/rooms{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/residences/{id}/relationships/rooms{?query*}", rawUrl) + { + } + + /// + /// Removes existing rooms from the rooms relationship of an individual residence. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task DeleteAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToDeleteRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related room identities of an individual residence's rooms relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.RoomIdentifierCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns existing rooms to the rooms relationship of an individual residence. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Adds existing rooms to the rooms relationship of an individual residence. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Removes existing rooms from the rooms relationship of an individual residence. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Retrieves the related room identities of an individual residence's rooms relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns existing rooms to the rooms relationship of an individual residence. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Adds existing rooms to the rooms relationship of an individual residence. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToManyRoomInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Residences.Item.Relationships.Rooms.RoomsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Residences.Item.Relationships.Rooms.RoomsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related room identities of an individual residence's rooms relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Residences/Item/ResidencesItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Residences/Item/ResidencesItemRequestBuilder.cs new file mode 100644 index 0000000000..0460573b86 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Residences/Item/ResidencesItemRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Residences.Item.Relationships; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Residences.Item +{ + /// + /// Builds and executes requests for operations under \residences\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidencesItemRequestBuilder : BaseRequestBuilder + { + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Residences.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Residences.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ResidencesItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/residences/{id}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ResidencesItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/residences/{id}", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Residences/ResidencesRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Residences/ResidencesRequestBuilder.cs new file mode 100644 index 0000000000..5dd0f2107e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Residences/ResidencesRequestBuilder.cs @@ -0,0 +1,52 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Residences.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Residences +{ + /// + /// Builds and executes requests for operations under \residences + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidencesRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.residences.item collection + /// The identifier of the residence whose related room identities to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Residences.Item.ResidencesItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Residences.Item.ResidencesItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ResidencesRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/residences", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ResidencesRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/residences", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Rooms/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Rooms/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..c2bf625624 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Rooms/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Rooms.Item.Relationships.Residence; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Rooms.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \rooms\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Rooms.Item.Relationships.Residence.ResidenceRequestBuilder Residence + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Rooms.Item.Relationships.Residence.ResidenceRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/rooms/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/rooms/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Rooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Rooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs new file mode 100644 index 0000000000..b6c5f16374 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Rooms/Item/Relationships/Residence/ResidenceRequestBuilder.cs @@ -0,0 +1,168 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Rooms.Item.Relationships.Residence +{ + /// + /// Builds and executes requests for operations under \rooms\{id}\relationships\residence + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/rooms/{id}/relationships/residence{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/rooms/{id}/relationships/residence{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related residence identity of an individual room's residence relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns an existing residence to the residence relationship of an individual room. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related residence identity of an individual room's residence relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns an existing residence to the residence relationship of an individual room. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Rooms.Item.Relationships.Residence.ResidenceRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Rooms.Item.Relationships.Residence.ResidenceRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related residence identity of an individual room's residence relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Rooms/Item/RoomsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Rooms/Item/RoomsItemRequestBuilder.cs new file mode 100644 index 0000000000..3dd1f57547 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Rooms/Item/RoomsItemRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Rooms.Item.Relationships; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Rooms.Item +{ + /// + /// Builds and executes requests for operations under \rooms\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsItemRequestBuilder : BaseRequestBuilder + { + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Rooms.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Rooms.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RoomsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/rooms/{id}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RoomsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/rooms/{id}", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Rooms/RoomsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Rooms/RoomsRequestBuilder.cs new file mode 100644 index 0000000000..ff88914623 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Rooms/RoomsRequestBuilder.cs @@ -0,0 +1,52 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Rooms.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Rooms +{ + /// + /// Builds and executes requests for operations under \rooms + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.rooms.item collection + /// The identifier of the room whose related residence identity to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Rooms.Item.RoomsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Rooms.Item.RoomsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/rooms", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/rooms", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Toilets/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Toilets/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..87db76543d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Toilets/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Toilets.Item.Relationships.Residence; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Toilets.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \toilets\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Toilets.Item.Relationships.Residence.ResidenceRequestBuilder Residence + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Toilets.Item.Relationships.Residence.ResidenceRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/toilets/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/toilets/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Toilets/Item/Relationships/Residence/ResidenceRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Toilets/Item/Relationships/Residence/ResidenceRequestBuilder.cs new file mode 100644 index 0000000000..70ceef10dc --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Toilets/Item/Relationships/Residence/ResidenceRequestBuilder.cs @@ -0,0 +1,168 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Toilets.Item.Relationships.Residence +{ + /// + /// Builds and executes requests for operations under \toilets\{id}\relationships\residence + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/toilets/{id}/relationships/residence{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ResidenceRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/toilets/{id}/relationships/residence{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related residence identity of an individual toilet's residence relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ResidenceIdentifierResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns an existing residence to the residence relationship of an individual toilet. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related residence identity of an individual toilet's residence relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns an existing residence to the residence relationship of an individual toilet. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models.ToOneResidenceInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Toilets.Item.Relationships.Residence.ResidenceRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Toilets.Item.Relationships.Residence.ResidenceRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related residence identity of an individual toilet's residence relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ResidenceRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Toilets/Item/ToiletsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Toilets/Item/ToiletsItemRequestBuilder.cs new file mode 100644 index 0000000000..9cb2ac94af --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Toilets/Item/ToiletsItemRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Toilets.Item.Relationships; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Toilets.Item +{ + /// + /// Builds and executes requests for operations under \toilets\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ToiletsItemRequestBuilder : BaseRequestBuilder + { + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Toilets.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Toilets.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ToiletsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/toilets/{id}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ToiletsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/toilets/{id}", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Toilets/ToiletsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Toilets/ToiletsRequestBuilder.cs new file mode 100644 index 0000000000..6e4af346e2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/Toilets/ToiletsRequestBuilder.cs @@ -0,0 +1,52 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Toilets.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Toilets +{ + /// + /// Builds and executes requests for operations under \toilets + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ToiletsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.toilets.item collection + /// The identifier of the toilet whose related residence identity to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Toilets.Item.ToiletsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Toilets.Item.ToiletsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ToiletsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/toilets", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ToiletsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/toilets", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/RelationshipInheritanceTests.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/RelationshipInheritanceTests.cs new file mode 100644 index 0000000000..51ce915018 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/RelationshipInheritanceTests.cs @@ -0,0 +1,913 @@ +using FluentAssertions; +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Middleware; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode; +using OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.ResourceInheritance; +using OpenApiTests.ResourceInheritance.Models; +using OpenApiTests.ResourceInheritance.OnlyRelationships; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships; + +public sealed class RelationshipInheritanceTests + : IClassFixture, ResourceInheritanceDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, ResourceInheritanceDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly ResourceInheritanceFakers _fakers = new(); + + public RelationshipInheritanceTests(IntegrationTestContext, ResourceInheritanceDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseInheritanceControllers(true); + + testContext.ConfigureServices(services => + { + services.AddSingleton(); + services.AddSingleton(); + }); + } + + // GET /rooms/1/relationships/residence => familyHome + [Fact] + public async Task Can_get_ToOne_relationship_at_abstract_base_endpoint() + { + // Arrange + Bedroom bedroom = _fakers.Bedroom.GenerateOne(); + bedroom.Residence = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Rooms.Add(bedroom); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new OnlyRelationshipsInheritanceClient(requestAdapter); + + // Act + ResidenceIdentifierResponseDocument? response = await apiClient.Rooms[bedroom.StringId!].Relationships.Residence.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().BeOfType(); + response.Data.Id.Should().Be(bedroom.Residence.StringId); + } + + // GET /bedrooms/1/relationships/residence => familyHome + [Fact] + public async Task Can_get_ToOne_relationship_at_concrete_derived_endpoint() + { + // Arrange + Bedroom bedroom = _fakers.Bedroom.GenerateOne(); + bedroom.Residence = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Rooms.Add(bedroom); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new OnlyRelationshipsInheritanceClient(requestAdapter); + + // Act + ResidenceIdentifierResponseDocument? response = await apiClient.Bedrooms[bedroom.StringId!].Relationships.Residence.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().BeOfType(); + response.Data.Id.Should().Be(bedroom.Residence.StringId); + } + + // GET /residences/1/relationships/rooms => [kitchen, bedroom] + [Fact] + public async Task Can_get_ToMany_relationship_at_concrete_base_endpoint() + { + // Arrange + Kitchen kitchen = _fakers.Kitchen.GenerateOne(); + Bedroom bedroom = _fakers.Bedroom.GenerateOne(); + + FamilyHome familyHome = _fakers.FamilyHome.GenerateOne(); + familyHome.Rooms.Add(kitchen); + familyHome.Rooms.Add(bedroom); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.FamilyHomes.Add(familyHome); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new OnlyRelationshipsInheritanceClient(requestAdapter); + + // Act + RoomIdentifierCollectionResponseDocument? response = await apiClient.Residences[familyHome.StringId!].Relationships.Rooms.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(2); + + response.Data.OfType().Should().ContainSingle(data => data.Id == kitchen.StringId); + response.Data.OfType().Should().ContainSingle(data => data.Id == bedroom.StringId); + } + + // GET /mansions/1/relationships/rooms => [bathroom, toilet] + [Fact] + public async Task Can_get_ToMany_relationship_at_concrete_derived_endpoint() + { + // Arrange + Bathroom bathroom = _fakers.Bathroom.GenerateOne(); + Toilet toilet = _fakers.Toilet.GenerateOne(); + + Mansion mansion = _fakers.Mansion.GenerateOne(); + mansion.Rooms.Add(bathroom); + mansion.Rooms.Add(toilet); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(mansion); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new OnlyRelationshipsInheritanceClient(requestAdapter); + + // Act + RoomIdentifierCollectionResponseDocument? response = await apiClient.Mansions[mansion.StringId!].Relationships.Rooms.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(2); + + response.Data.OfType().Should().ContainSingle(data => data.Id == bathroom.StringId); + response.Data.OfType().Should().ContainSingle(data => data.Id == toilet.StringId); + } + + // PATCH /rooms/1/relationships/residence { type: residence } + [Fact] + public async Task Can_set_concrete_base_resource_at_abstract_ToOne_relationship_endpoint() + { + // Arrange + Bathroom existingBathroom = _fakers.Bathroom.GenerateOne(); + existingBathroom.Residence = _fakers.FamilyHome.GenerateOne(); + + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Bathrooms.Add(existingBathroom); + dbContext.Mansions.Add(existingMansion); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new OnlyRelationshipsInheritanceClient(requestAdapter); + + var requestBody = new ToOneResidenceInRequest + { + Data = new ResidenceIdentifierInRequest + { + Type = ResourceType.Residences, + Id = existingMansion.StringId + } + }; + + // Act + await apiClient.Rooms[existingBathroom.StringId!].Relationships.Residence.PatchAsync(requestBody); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Room roomInDatabase = await dbContext.Rooms.Include(room => room.Residence).FirstWithIdAsync(existingBathroom.Id); + + roomInDatabase.Should().BeOfType(); + + roomInDatabase.Residence.Should().BeOfType(); + roomInDatabase.Residence.Id.Should().Be(existingMansion.Id); + }); + } + + // PATCH /rooms/1/relationships/residence { type: mansion } + [Fact] + public async Task Can_set_concrete_derived_resource_at_abstract_ToOne_relationship_endpoint() + { + // Arrange + Bathroom existingBathroom = _fakers.Bathroom.GenerateOne(); + existingBathroom.Residence = _fakers.FamilyHome.GenerateOne(); + + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Bathrooms.Add(existingBathroom); + dbContext.Mansions.Add(existingMansion); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new OnlyRelationshipsInheritanceClient(requestAdapter); + + var requestBody = new ToOneResidenceInRequest + { + Data = new MansionIdentifierInRequest + { + Type = ResourceType.Mansions, + Id = existingMansion.StringId + } + }; + + // Act + await apiClient.Rooms[existingBathroom.StringId!].Relationships.Residence.PatchAsync(requestBody); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Room roomInDatabase = await dbContext.Rooms.Include(room => room.Residence).FirstWithIdAsync(existingBathroom.Id); + + roomInDatabase.Should().BeOfType(); + + roomInDatabase.Residence.Should().BeOfType(); + roomInDatabase.Residence.Id.Should().Be(existingMansion.Id); + }); + } + + // PATCH /bathrooms/1/relationships/residence { type: residence } + [Fact] + public async Task Can_set_concrete_base_resource_at_concrete_derived_ToOne_relationship_endpoint() + { + // Arrange + Bathroom existingBathroom = _fakers.Bathroom.GenerateOne(); + existingBathroom.Residence = _fakers.FamilyHome.GenerateOne(); + + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Bathrooms.Add(existingBathroom); + dbContext.Mansions.Add(existingMansion); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new OnlyRelationshipsInheritanceClient(requestAdapter); + + var requestBody = new ToOneResidenceInRequest + { + Data = new ResidenceIdentifierInRequest + { + Type = ResourceType.Residences, + Id = existingMansion.StringId + } + }; + + // Act + await apiClient.Bathrooms[existingBathroom.StringId!].Relationships.Residence.PatchAsync(requestBody); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Room roomInDatabase = await dbContext.Rooms.Include(room => room.Residence).FirstWithIdAsync(existingBathroom.Id); + + roomInDatabase.Should().BeOfType(); + + roomInDatabase.Residence.Should().BeOfType(); + roomInDatabase.Residence.Id.Should().Be(existingMansion.Id); + }); + } + + // PATCH /bathrooms/1/relationships/residence { type: mansion } + [Fact] + public async Task Can_set_concrete_derived_resource_at_concrete_derived_ToOne_relationship_endpoint() + { + // Arrange + Bathroom existingBathroom = _fakers.Bathroom.GenerateOne(); + existingBathroom.Residence = _fakers.FamilyHome.GenerateOne(); + + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Bathrooms.Add(existingBathroom); + dbContext.Mansions.Add(existingMansion); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new OnlyRelationshipsInheritanceClient(requestAdapter); + + var requestBody = new ToOneResidenceInRequest + { + Data = new MansionIdentifierInRequest + { + Type = ResourceType.Mansions, + Id = existingMansion.StringId + } + }; + + // Act + await apiClient.Bathrooms[existingBathroom.StringId!].Relationships.Residence.PatchAsync(requestBody); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Room roomInDatabase = await dbContext.Rooms.Include(room => room.Residence).FirstWithIdAsync(existingBathroom.Id); + + roomInDatabase.Should().BeOfType(); + + roomInDatabase.Residence.Should().BeOfType(); + roomInDatabase.Residence.Id.Should().Be(existingMansion.Id); + }); + } + + // PATCH /residences/1/relationships/rooms { type: room } + [Fact] + public async Task Can_set_abstract_resources_at_concrete_base_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + existingMansion.Rooms = _fakers.LivingRoom.GenerateSet(1); + + Bedroom existingBedroom = _fakers.Bedroom.GenerateOne(); + existingBedroom.Residence = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + dbContext.Bedrooms.Add(existingBedroom); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new OnlyRelationshipsInheritanceClient(requestAdapter); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new RoomIdentifierInRequest + { + Type = ResourceType.Rooms, + Id = existingBedroom.StringId + } + ] + }; + + // Act + await apiClient.Residences[existingMansion.StringId!].Relationships.Rooms.PatchAsync(requestBody); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().HaveCount(1); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom.Id); + }); + } + + // PATCH /residences/1/relationships/rooms { type: bedroom } + [Fact] + public async Task Can_set_concrete_derived_resources_at_concrete_base_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + existingMansion.Rooms = _fakers.LivingRoom.GenerateSet(1); + + Bedroom existingBedroom = _fakers.Bedroom.GenerateOne(); + existingBedroom.Residence = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + dbContext.Bedrooms.Add(existingBedroom); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new OnlyRelationshipsInheritanceClient(requestAdapter); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new BedroomIdentifierInRequest + { + Type = ResourceType.Bedrooms, + Id = existingBedroom.StringId + } + ] + }; + + // Act + await apiClient.Residences[existingMansion.StringId!].Relationships.Rooms.PatchAsync(requestBody); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().HaveCount(1); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom.Id); + }); + } + + // PATCH /mansions/1/relationships/rooms { type: room } + [Fact] + public async Task Can_set_abstract_resources_at_concrete_derived_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + existingMansion.Rooms = _fakers.LivingRoom.GenerateSet(1); + + Bedroom existingBedroom = _fakers.Bedroom.GenerateOne(); + existingBedroom.Residence = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + dbContext.Bedrooms.Add(existingBedroom); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new OnlyRelationshipsInheritanceClient(requestAdapter); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new RoomIdentifierInRequest + { + Type = ResourceType.Rooms, + Id = existingBedroom.StringId + } + ] + }; + + // Act + await apiClient.Mansions[existingMansion.StringId!].Relationships.Rooms.PatchAsync(requestBody); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().HaveCount(1); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom.Id); + }); + } + + // PATCH /mansions/1/relationships/rooms { type: bedroom } + [Fact] + public async Task Can_set_concrete_derived_resources_at_concrete_derived_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + existingMansion.Rooms = _fakers.LivingRoom.GenerateSet(1); + + Bedroom existingBedroom = _fakers.Bedroom.GenerateOne(); + existingBedroom.Residence = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + dbContext.Bedrooms.Add(existingBedroom); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new OnlyRelationshipsInheritanceClient(requestAdapter); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new BedroomIdentifierInRequest + { + Type = ResourceType.Bedrooms, + Id = existingBedroom.StringId + } + ] + }; + + // Act + await apiClient.Mansions[existingMansion.StringId!].Relationships.Rooms.PatchAsync(requestBody); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().HaveCount(1); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom.Id); + }); + } + + // POST /residences/1/relationships/rooms { type: room } + [Fact] + public async Task Can_add_abstract_resource_at_concrete_base_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + LivingRoom existingLivingRoom = _fakers.LivingRoom.GenerateOne(); + existingMansion.Rooms.Add(existingLivingRoom); + + Bedroom existingBedroom = _fakers.Bedroom.GenerateOne(); + existingBedroom.Residence = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + dbContext.Bedrooms.Add(existingBedroom); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new OnlyRelationshipsInheritanceClient(requestAdapter); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new RoomIdentifierInRequest + { + Type = ResourceType.Rooms, + Id = existingBedroom.StringId + } + ] + }; + + // Act + await apiClient.Residences[existingMansion.StringId!].Relationships.Rooms.PostAsync(requestBody); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().HaveCount(2); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(livingRoom => livingRoom.Id == existingLivingRoom.Id); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom.Id); + }); + } + + // POST /residences/1/relationships/rooms { type: bedroom } + [Fact] + public async Task Can_add_concrete_derived_resource_at_concrete_base_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + LivingRoom existingLivingRoom = _fakers.LivingRoom.GenerateOne(); + existingMansion.Rooms.Add(existingLivingRoom); + + Bedroom existingBedroom = _fakers.Bedroom.GenerateOne(); + existingBedroom.Residence = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + dbContext.Bedrooms.Add(existingBedroom); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new OnlyRelationshipsInheritanceClient(requestAdapter); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new BedroomIdentifierInRequest + { + Type = ResourceType.Bedrooms, + Id = existingBedroom.StringId + } + ] + }; + + // Act + await apiClient.Residences[existingMansion.StringId!].Relationships.Rooms.PostAsync(requestBody); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().HaveCount(2); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(livingRoom => livingRoom.Id == existingLivingRoom.Id); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom.Id); + }); + } + + // POST /mansions/1/relationships/rooms { type: room } + [Fact] + public async Task Can_add_abstract_resource_at_concrete_derived_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + LivingRoom existingLivingRoom = _fakers.LivingRoom.GenerateOne(); + existingMansion.Rooms.Add(existingLivingRoom); + + Bedroom existingBedroom = _fakers.Bedroom.GenerateOne(); + existingBedroom.Residence = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + dbContext.Bedrooms.Add(existingBedroom); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new OnlyRelationshipsInheritanceClient(requestAdapter); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new RoomIdentifierInRequest + { + Type = ResourceType.Bedrooms, + Id = existingBedroom.StringId + } + ] + }; + + // Act + await apiClient.Mansions[existingMansion.StringId!].Relationships.Rooms.PostAsync(requestBody); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().HaveCount(2); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(livingRoom => livingRoom.Id == existingLivingRoom.Id); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom.Id); + }); + } + + // POST /mansions/1/relationships/rooms { type: bedroom } + [Fact] + public async Task Can_add_concrete_derived_resource_at_concrete_derived_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + LivingRoom existingLivingRoom = _fakers.LivingRoom.GenerateOne(); + existingMansion.Rooms.Add(existingLivingRoom); + + Bedroom existingBedroom = _fakers.Bedroom.GenerateOne(); + existingBedroom.Residence = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + dbContext.Bedrooms.Add(existingBedroom); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new OnlyRelationshipsInheritanceClient(requestAdapter); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new BedroomIdentifierInRequest + { + Type = ResourceType.Bedrooms, + Id = existingBedroom.StringId + } + ] + }; + + // Act + await apiClient.Mansions[existingMansion.StringId!].Relationships.Rooms.PostAsync(requestBody); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().HaveCount(2); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(livingRoom => livingRoom.Id == existingLivingRoom.Id); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom.Id); + }); + } + + // DELETE /residences/1/relationships/rooms { type: room } + [Fact] + public async Task Can_remove_abstract_resource_at_concrete_base_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + existingMansion.Rooms = _fakers.LivingRoom.GenerateSet(1); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new OnlyRelationshipsInheritanceClient(requestAdapter); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new RoomIdentifierInRequest + { + Type = ResourceType.Rooms, + Id = existingMansion.Rooms.ElementAt(0).StringId + } + ] + }; + + // Act + await apiClient.Residences[existingMansion.StringId!].Relationships.Rooms.DeleteAsync(requestBody); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().BeEmpty(); + }); + } + + // DELETE /residences/1/relationships/rooms { type: bedroom } + [Fact] + public async Task Can_remove_concrete_derived_resource_at_concrete_base_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + existingMansion.Rooms = _fakers.Bedroom.GenerateSet(1); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new OnlyRelationshipsInheritanceClient(requestAdapter); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new BedroomIdentifierInRequest + { + Type = ResourceType.Bedrooms, + Id = existingMansion.Rooms.ElementAt(0).StringId + } + ] + }; + + // Act + await apiClient.Residences[existingMansion.StringId!].Relationships.Rooms.DeleteAsync(requestBody); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().BeEmpty(); + }); + } + + // DELETE /mansions/1/relationships/rooms { type: room } + [Fact] + public async Task Can_remove_abstract_resource_at_concrete_derived_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + existingMansion.Rooms = _fakers.LivingRoom.GenerateSet(1); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new OnlyRelationshipsInheritanceClient(requestAdapter); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new RoomIdentifierInRequest + { + Type = ResourceType.Rooms, + Id = existingMansion.Rooms.ElementAt(0).StringId + } + ] + }; + + // Act + await apiClient.Mansions[existingMansion.StringId!].Relationships.Rooms.DeleteAsync(requestBody); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().BeEmpty(); + }); + } + + // DELETE /mansions/1/relationships/rooms { type: bedroom } + [Fact] + public async Task Can_remove_concrete_derived_resource_at_concrete_derived_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + existingMansion.Rooms = _fakers.Bedroom.GenerateSet(1); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new OnlyRelationshipsInheritanceClient(requestAdapter); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new BedroomIdentifierInRequest + { + Type = ResourceType.Bedrooms, + Id = existingMansion.Rooms.ElementAt(0).StringId + } + ] + }; + + // Act + await apiClient.Mansions[existingMansion.StringId!].Relationships.Rooms.DeleteAsync(requestBody); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().BeEmpty(); + }); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AddOperationCode.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AddOperationCode.cs new file mode 100644 index 0000000000..819a6719fa --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AddOperationCode.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum AddOperationCode + #pragma warning restore CS1591 + { + [EnumMember(Value = "add")] + #pragma warning disable CS1591 + Add, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AddToFamilyHomeRoomsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AddToFamilyHomeRoomsRelationshipOperation.cs new file mode 100644 index 0000000000..9122113872 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AddToFamilyHomeRoomsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AddToFamilyHomeRoomsRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AddOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.FamilyHomeRoomsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AddToFamilyHomeRoomsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AddToFamilyHomeRoomsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.FamilyHomeRoomsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AtomicOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AtomicOperation.cs new file mode 100644 index 0000000000..533529ecb9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AtomicOperation.cs @@ -0,0 +1,104 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AtomicOperation : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The openapiDiscriminator property + public string? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AtomicOperation() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AtomicOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "addBathroom" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateBathroomOperation(), + "addBedroom" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateBedroomOperation(), + "addFamilyHome" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateFamilyHomeOperation(), + "addKitchen" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateKitchenOperation(), + "addLivingRoom" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateLivingRoomOperation(), + "addMansion" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateMansionOperation(), + "addResidence" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateResidenceOperation(), + "addRoom" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateRoomOperation(), + "addToFamilyHomeRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AddToFamilyHomeRoomsRelationshipOperation(), + "addToilet" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateToiletOperation(), + "removeFromMansionRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RemoveFromMansionRoomsRelationshipOperation(), + "removeFromMansionStaff" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RemoveFromMansionStaffRelationshipOperation(), + "updateBathroomResidence" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateBathroomResidenceRelationshipOperation(), + "updateBedroomResidence" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateBedroomResidenceRelationshipOperation(), + "updateFamilyHome" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateFamilyHomeOperation(), + "updateKitchenResidence" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateKitchenResidenceRelationshipOperation(), + "updateLivingRoomResidence" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateLivingRoomResidenceRelationshipOperation(), + "updateMansion" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateMansionOperation(), + "updateResidence" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateResidenceOperation(), + "updateRoomResidence" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateRoomResidenceRelationshipOperation(), + "updateToiletResidence" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateToiletResidenceRelationshipOperation(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AtomicOperation(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteStringValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AtomicResult.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AtomicResult.cs new file mode 100644 index 0000000000..189db8df34 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AtomicResult.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AtomicResult : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AtomicResult() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AtomicResult CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AtomicResult(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInBathroomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInBathroomResponse.cs new file mode 100644 index 0000000000..98f9ccbb28 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInBathroomResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInBathroomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// The hasBath property + public bool? HasBath + { + get { return BackingStore?.Get("hasBath"); } + set { BackingStore?.Set("hasBath", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInBathroomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInBathroomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasBath", n => { HasBath = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasBath", HasBath); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInBedroomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInBedroomResponse.cs new file mode 100644 index 0000000000..e5affa67a8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInBedroomResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInBedroomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// The bedCount property + public int? BedCount + { + get { return BackingStore?.Get("bedCount"); } + set { BackingStore?.Set("bedCount", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInBedroomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInBedroomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "bedCount", n => { BedCount = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("bedCount", BedCount); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInBuildingResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInBuildingResponse.cs new file mode 100644 index 0000000000..b0b3b0e1e6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInBuildingResponse.cs @@ -0,0 +1,66 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInBuildingResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The surfaceInSquareMeters property + public int? SurfaceInSquareMeters + { + get { return BackingStore?.Get("surfaceInSquareMeters"); } + set { BackingStore?.Set("surfaceInSquareMeters", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInBuildingResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInFamilyHomeResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInMansionResponse(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInResidenceResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInBuildingResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "surfaceInSquareMeters", n => { SurfaceInSquareMeters = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("surfaceInSquareMeters", SurfaceInSquareMeters); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateBathroomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateBathroomRequest.cs new file mode 100644 index 0000000000..a091d48395 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateBathroomRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateBathroomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// The hasBath property + public bool? HasBath + { + get { return BackingStore?.Get("hasBath"); } + set { BackingStore?.Set("hasBath", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateBathroomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateBathroomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasBath", n => { HasBath = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasBath", HasBath); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateBedroomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateBedroomRequest.cs new file mode 100644 index 0000000000..854cf0e850 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateBedroomRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateBedroomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// The bedCount property + public int? BedCount + { + get { return BackingStore?.Get("bedCount"); } + set { BackingStore?.Set("bedCount", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateBedroomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateBedroomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "bedCount", n => { BedCount = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("bedCount", BedCount); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateBuildingRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateBuildingRequest.cs new file mode 100644 index 0000000000..e8214666de --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateBuildingRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateBuildingRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The surfaceInSquareMeters property + public int? SurfaceInSquareMeters + { + get { return BackingStore?.Get("surfaceInSquareMeters"); } + set { BackingStore?.Set("surfaceInSquareMeters", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateBuildingRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateBuildingRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "surfaceInSquareMeters", n => { SurfaceInSquareMeters = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("surfaceInSquareMeters", SurfaceInSquareMeters); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateFamilyHomeRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateFamilyHomeRequest.cs new file mode 100644 index 0000000000..fc292a733a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateFamilyHomeRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateFamilyHomeRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// The floorCount property + public int? FloorCount + { + get { return BackingStore?.Get("floorCount"); } + set { BackingStore?.Set("floorCount", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateFamilyHomeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateFamilyHomeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "floorCount", n => { FloorCount = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("floorCount", FloorCount); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateKitchenRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateKitchenRequest.cs new file mode 100644 index 0000000000..892c3668ca --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateKitchenRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateKitchenRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// The hasPantry property + public bool? HasPantry + { + get { return BackingStore?.Get("hasPantry"); } + set { BackingStore?.Set("hasPantry", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateKitchenRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateKitchenRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasPantry", n => { HasPantry = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasPantry", HasPantry); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateLivingRoomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateLivingRoomRequest.cs new file mode 100644 index 0000000000..f53b83cdf3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateLivingRoomRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateLivingRoomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// The hasDiningTable property + public bool? HasDiningTable + { + get { return BackingStore?.Get("hasDiningTable"); } + set { BackingStore?.Set("hasDiningTable", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateLivingRoomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateLivingRoomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasDiningTable", n => { HasDiningTable = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasDiningTable", HasDiningTable); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateMansionRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateMansionRequest.cs new file mode 100644 index 0000000000..c1e61f73fc --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateMansionRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateMansionRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// The ownerName property + public string? OwnerName + { + get { return BackingStore?.Get("ownerName"); } + set { BackingStore?.Set("ownerName", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateMansionRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateMansionRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "ownerName", n => { OwnerName = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("ownerName", OwnerName); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateRequest.cs new file mode 100644 index 0000000000..0ce7fd18a5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateRequest.cs @@ -0,0 +1,84 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateBathroomRequest(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateBedroomRequest(), + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateBuildingRequest(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateFamilyHomeRequest(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateKitchenRequest(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateLivingRoomRequest(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateMansionRequest(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateResidenceRequest(), + "rooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateRoomRequest(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateToiletRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateResidenceRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateResidenceRequest.cs new file mode 100644 index 0000000000..ff14472361 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateResidenceRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateResidenceRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateBuildingRequest, IParsable + #pragma warning restore CS1591 + { + /// The numberOfResidents property + public int? NumberOfResidents + { + get { return BackingStore?.Get("numberOfResidents"); } + set { BackingStore?.Set("numberOfResidents", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateResidenceRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateResidenceRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "numberOfResidents", n => { NumberOfResidents = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("numberOfResidents", NumberOfResidents); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateRoomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateRoomRequest.cs new file mode 100644 index 0000000000..1dbc602b9b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateRoomRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateRoomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The surfaceInSquareMeters property + public int? SurfaceInSquareMeters + { + get { return BackingStore?.Get("surfaceInSquareMeters"); } + set { BackingStore?.Set("surfaceInSquareMeters", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateRoomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateRoomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "surfaceInSquareMeters", n => { SurfaceInSquareMeters = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("surfaceInSquareMeters", SurfaceInSquareMeters); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateToiletRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateToiletRequest.cs new file mode 100644 index 0000000000..03ecd3ccd4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInCreateToiletRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateToiletRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// The hasSink property + public bool? HasSink + { + get { return BackingStore?.Get("hasSink"); } + set { BackingStore?.Set("hasSink", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateToiletRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateToiletRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasSink", n => { HasSink = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasSink", HasSink); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInFamilyHomeResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInFamilyHomeResponse.cs new file mode 100644 index 0000000000..e91dda6c0f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInFamilyHomeResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInFamilyHomeResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInResidenceResponse, IParsable + #pragma warning restore CS1591 + { + /// The floorCount property + public int? FloorCount + { + get { return BackingStore?.Get("floorCount"); } + set { BackingStore?.Set("floorCount", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInFamilyHomeResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInFamilyHomeResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "floorCount", n => { FloorCount = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("floorCount", FloorCount); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInKitchenResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInKitchenResponse.cs new file mode 100644 index 0000000000..25243a6e64 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInKitchenResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInKitchenResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// The hasPantry property + public bool? HasPantry + { + get { return BackingStore?.Get("hasPantry"); } + set { BackingStore?.Set("hasPantry", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInKitchenResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInKitchenResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasPantry", n => { HasPantry = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasPantry", HasPantry); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInLivingRoomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInLivingRoomResponse.cs new file mode 100644 index 0000000000..2f94318bc6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInLivingRoomResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInLivingRoomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// The hasDiningTable property + public bool? HasDiningTable + { + get { return BackingStore?.Get("hasDiningTable"); } + set { BackingStore?.Set("hasDiningTable", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInLivingRoomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInLivingRoomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasDiningTable", n => { HasDiningTable = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasDiningTable", HasDiningTable); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInMansionResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInMansionResponse.cs new file mode 100644 index 0000000000..3035f0a06f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInMansionResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInMansionResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInResidenceResponse, IParsable + #pragma warning restore CS1591 + { + /// The ownerName property + public string? OwnerName + { + get { return BackingStore?.Get("ownerName"); } + set { BackingStore?.Set("ownerName", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInMansionResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInMansionResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "ownerName", n => { OwnerName = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("ownerName", OwnerName); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInResidenceResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInResidenceResponse.cs new file mode 100644 index 0000000000..7478c31f8d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInResidenceResponse.cs @@ -0,0 +1,65 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInResidenceResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInBuildingResponse, IParsable + #pragma warning restore CS1591 + { + /// The numberOfResidents property + public int? NumberOfResidents + { + get { return BackingStore?.Get("numberOfResidents"); } + set { BackingStore?.Set("numberOfResidents", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInResidenceResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInFamilyHomeResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInMansionResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInResidenceResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "numberOfResidents", n => { NumberOfResidents = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("numberOfResidents", NumberOfResidents); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInResponse.cs new file mode 100644 index 0000000000..7947bafc0d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInResponse.cs @@ -0,0 +1,84 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInBathroomResponse(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInBedroomResponse(), + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInBuildingResponse(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInFamilyHomeResponse(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInKitchenResponse(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInLivingRoomResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInMansionResponse(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInResidenceResponse(), + "rooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInRoomResponse(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInToiletResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInRoomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInRoomResponse.cs new file mode 100644 index 0000000000..1565e0301b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInRoomResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInRoomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The surfaceInSquareMeters property + public int? SurfaceInSquareMeters + { + get { return BackingStore?.Get("surfaceInSquareMeters"); } + set { BackingStore?.Set("surfaceInSquareMeters", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInRoomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInBathroomResponse(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInBedroomResponse(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInKitchenResponse(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInLivingRoomResponse(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInToiletResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInRoomResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "surfaceInSquareMeters", n => { SurfaceInSquareMeters = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("surfaceInSquareMeters", SurfaceInSquareMeters); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInToiletResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInToiletResponse.cs new file mode 100644 index 0000000000..3b313fe0d8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInToiletResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInToiletResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// The hasSink property + public bool? HasSink + { + get { return BackingStore?.Get("hasSink"); } + set { BackingStore?.Set("hasSink", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInToiletResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInToiletResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasSink", n => { HasSink = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasSink", HasSink); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInUpdateBuildingRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInUpdateBuildingRequest.cs new file mode 100644 index 0000000000..71c24d37b1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInUpdateBuildingRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateBuildingRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The surfaceInSquareMeters property + public int? SurfaceInSquareMeters + { + get { return BackingStore?.Get("surfaceInSquareMeters"); } + set { BackingStore?.Set("surfaceInSquareMeters", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInUpdateBuildingRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInUpdateBuildingRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "surfaceInSquareMeters", n => { SurfaceInSquareMeters = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("surfaceInSquareMeters", SurfaceInSquareMeters); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInUpdateFamilyHomeRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInUpdateFamilyHomeRequest.cs new file mode 100644 index 0000000000..e40e228f61 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInUpdateFamilyHomeRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateFamilyHomeRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInUpdateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// The floorCount property + public int? FloorCount + { + get { return BackingStore?.Get("floorCount"); } + set { BackingStore?.Set("floorCount", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInUpdateFamilyHomeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInUpdateFamilyHomeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "floorCount", n => { FloorCount = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("floorCount", FloorCount); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInUpdateMansionRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInUpdateMansionRequest.cs new file mode 100644 index 0000000000..64431ad387 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInUpdateMansionRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateMansionRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInUpdateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// The ownerName property + public string? OwnerName + { + get { return BackingStore?.Get("ownerName"); } + set { BackingStore?.Set("ownerName", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInUpdateMansionRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInUpdateMansionRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "ownerName", n => { OwnerName = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("ownerName", OwnerName); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInUpdateRequest.cs new file mode 100644 index 0000000000..9471064dd5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInUpdateRequest.cs @@ -0,0 +1,78 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInUpdateBuildingRequest(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInUpdateFamilyHomeRequest(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInUpdateMansionRequest(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInUpdateResidenceRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInUpdateResidenceRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInUpdateResidenceRequest.cs new file mode 100644 index 0000000000..439b6e3db1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/AttributesInUpdateResidenceRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateResidenceRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInUpdateBuildingRequest, IParsable + #pragma warning restore CS1591 + { + /// The numberOfResidents property + public int? NumberOfResidents + { + get { return BackingStore?.Get("numberOfResidents"); } + set { BackingStore?.Set("numberOfResidents", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInUpdateResidenceRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInUpdateResidenceRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "numberOfResidents", n => { NumberOfResidents = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("numberOfResidents", NumberOfResidents); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/BathroomIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/BathroomIdentifierInRequest.cs new file mode 100644 index 0000000000..aa77201377 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/BathroomIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BathroomIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.BathroomIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.BathroomIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/BathroomIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/BathroomIdentifierInResponse.cs new file mode 100644 index 0000000000..e3c01d0ca0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/BathroomIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BathroomIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.BathroomIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.BathroomIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/BedroomIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/BedroomIdentifierInRequest.cs new file mode 100644 index 0000000000..3f5ea328d1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/BedroomIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BedroomIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.BedroomIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.BedroomIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/BedroomIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/BedroomIdentifierInResponse.cs new file mode 100644 index 0000000000..192d06f0a6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/BedroomIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BedroomIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.BedroomIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.BedroomIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/BuildingIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/BuildingIdentifierInRequest.cs new file mode 100644 index 0000000000..71fbaef20d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/BuildingIdentifierInRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BuildingIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.BuildingIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.BuildingIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/BuildingIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/BuildingIdentifierInResponse.cs new file mode 100644 index 0000000000..43b3757972 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/BuildingIdentifierInResponse.cs @@ -0,0 +1,95 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BuildingIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.BuildingResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public BuildingIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.BuildingIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.FamilyHomeIdentifierInResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.MansionIdentifierInResponse(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResidenceIdentifierInResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.BuildingIdentifierInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/BuildingResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/BuildingResourceType.cs new file mode 100644 index 0000000000..1101a8853d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/BuildingResourceType.cs @@ -0,0 +1,26 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum BuildingResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "familyHomes")] + #pragma warning disable CS1591 + FamilyHomes, + #pragma warning restore CS1591 + [EnumMember(Value = "mansions")] + #pragma warning disable CS1591 + Mansions, + #pragma warning restore CS1591 + [EnumMember(Value = "residences")] + #pragma warning disable CS1591 + Residences, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateBathroomOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateBathroomOperation.cs new file mode 100644 index 0000000000..1dc8648c8d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateBathroomOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateBathroomOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateRoomOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateBathroomOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateBathroomOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateBedroomOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateBedroomOperation.cs new file mode 100644 index 0000000000..0bd80b987b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateBedroomOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateBedroomOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateRoomOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateBedroomOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateBedroomOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateFamilyHomeOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateFamilyHomeOperation.cs new file mode 100644 index 0000000000..4ac8dd7275 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateFamilyHomeOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateFamilyHomeOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateResidenceOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateFamilyHomeOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateFamilyHomeOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateKitchenOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateKitchenOperation.cs new file mode 100644 index 0000000000..5109ac68e6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateKitchenOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateKitchenOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateRoomOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateKitchenOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateKitchenOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateLivingRoomOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateLivingRoomOperation.cs new file mode 100644 index 0000000000..7dc4a8c470 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateLivingRoomOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateLivingRoomOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateRoomOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateLivingRoomOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateLivingRoomOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateMansionOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateMansionOperation.cs new file mode 100644 index 0000000000..62cbfe268b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateMansionOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateMansionOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateResidenceOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateMansionOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateMansionOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateResidenceOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateResidenceOperation.cs new file mode 100644 index 0000000000..45d0ca7632 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateResidenceOperation.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateResidenceOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateResidenceRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AddOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateResidenceOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateResidenceOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateResidenceRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateRoomOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateRoomOperation.cs new file mode 100644 index 0000000000..5d4b82e81c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateRoomOperation.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateRoomOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateRoomRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AddOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateRoomOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateRoomOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateRoomRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateToiletOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateToiletOperation.cs new file mode 100644 index 0000000000..e141dcf45c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/CreateToiletOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateToiletOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateRoomOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateToiletOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.CreateToiletOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInBathroomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInBathroomResponse.cs new file mode 100644 index 0000000000..209e60e20c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInBathroomResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInBathroomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInBathroomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInBathroomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInBedroomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInBedroomResponse.cs new file mode 100644 index 0000000000..b9c0185eb1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInBedroomResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInBedroomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInBedroomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInBedroomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInBuildingResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInBuildingResponse.cs new file mode 100644 index 0000000000..47dbd2fd41 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInBuildingResponse.cs @@ -0,0 +1,93 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInBuildingResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInBuildingResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInBuildingResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInBuildingResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInFamilyHomeResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInMansionResponse(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInResidenceResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInBuildingResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInBuildingResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInBuildingResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateBathroomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateBathroomRequest.cs new file mode 100644 index 0000000000..081b74e99c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateBathroomRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateBathroomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateBathroomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateBathroomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateBedroomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateBedroomRequest.cs new file mode 100644 index 0000000000..537a8cca38 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateBedroomRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateBedroomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateBedroomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateBedroomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateBuildingRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateBuildingRequest.cs new file mode 100644 index 0000000000..5f489f6974 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateBuildingRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateBuildingRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateBuildingRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateBuildingRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateBuildingRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateBuildingRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateBuildingRequest.CreateFromDiscriminatorValue); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateBuildingRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateFamilyHomeRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateFamilyHomeRequest.cs new file mode 100644 index 0000000000..96e4076338 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateFamilyHomeRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateFamilyHomeRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateFamilyHomeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateFamilyHomeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateKitchenRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateKitchenRequest.cs new file mode 100644 index 0000000000..6c15e646ab --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateKitchenRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateKitchenRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateKitchenRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateKitchenRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateLivingRoomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateLivingRoomRequest.cs new file mode 100644 index 0000000000..ae7e7358ba --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateLivingRoomRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateLivingRoomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateLivingRoomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateLivingRoomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateMansionRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateMansionRequest.cs new file mode 100644 index 0000000000..8c8be64e13 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateMansionRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateMansionRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateMansionRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateMansionRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateResidenceRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateResidenceRequest.cs new file mode 100644 index 0000000000..24059018f0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateResidenceRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateResidenceRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateBuildingRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateResidenceRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateResidenceRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateRoomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateRoomRequest.cs new file mode 100644 index 0000000000..bb8415c42f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateRoomRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateRoomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateRoomRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateRoomRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateRoomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateRoomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInCreateRoomRequest.CreateFromDiscriminatorValue); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateRoomRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateToiletRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateToiletRequest.cs new file mode 100644 index 0000000000..ebe9e9e410 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInCreateToiletRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateToiletRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateToiletRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateToiletRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInFamilyHomeResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInFamilyHomeResponse.cs new file mode 100644 index 0000000000..87c8905d40 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInFamilyHomeResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInFamilyHomeResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInResidenceResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInFamilyHomeResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInFamilyHomeResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInKitchenResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInKitchenResponse.cs new file mode 100644 index 0000000000..b8fb9a81b5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInKitchenResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInKitchenResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInKitchenResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInKitchenResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInLivingRoomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInLivingRoomResponse.cs new file mode 100644 index 0000000000..58e824d1a4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInLivingRoomResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInLivingRoomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInLivingRoomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInLivingRoomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInMansionResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInMansionResponse.cs new file mode 100644 index 0000000000..f66ac6f6cc --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInMansionResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInMansionResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInResidenceResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInMansionResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInMansionResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInResidenceResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInResidenceResponse.cs new file mode 100644 index 0000000000..e6af095df7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInResidenceResponse.cs @@ -0,0 +1,56 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInResidenceResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInBuildingResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInResidenceResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInFamilyHomeResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInMansionResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInResidenceResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInRoomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInRoomResponse.cs new file mode 100644 index 0000000000..69349b71c1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInRoomResponse.cs @@ -0,0 +1,95 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInRoomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInRoomResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInRoomResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInRoomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInBathroomResponse(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInBedroomResponse(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInKitchenResponse(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInLivingRoomResponse(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInToiletResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInRoomResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInRoomResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInRoomResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInToiletResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInToiletResponse.cs new file mode 100644 index 0000000000..e935922e06 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInToiletResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInToiletResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInToiletResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInToiletResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInUpdateBuildingRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInUpdateBuildingRequest.cs new file mode 100644 index 0000000000..ac5872448d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInUpdateBuildingRequest.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateBuildingRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInUpdateBuildingRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInUpdateBuildingRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInUpdateBuildingRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInUpdateBuildingRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AttributesInUpdateBuildingRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInUpdateBuildingRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInUpdateFamilyHomeRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInUpdateFamilyHomeRequest.cs new file mode 100644 index 0000000000..c8a964a981 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInUpdateFamilyHomeRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateFamilyHomeRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInUpdateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInUpdateFamilyHomeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInUpdateFamilyHomeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInUpdateMansionRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInUpdateMansionRequest.cs new file mode 100644 index 0000000000..2298f480bd --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInUpdateMansionRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateMansionRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInUpdateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInUpdateMansionRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInUpdateMansionRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInUpdateResidenceRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInUpdateResidenceRequest.cs new file mode 100644 index 0000000000..59e28a79c1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/DataInUpdateResidenceRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateResidenceRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInUpdateBuildingRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInUpdateResidenceRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInUpdateResidenceRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ErrorLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ErrorLinks.cs new file mode 100644 index 0000000000..63f0f363e0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ErrorLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// The about property + public string? About + { + get { return BackingStore?.Get("about"); } + set { BackingStore?.Set("about", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The type property + public string? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ErrorLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ErrorLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "about", n => { About = n.GetStringValue(); } }, + { "type", n => { Type = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("about", About); + writer.WriteStringValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ErrorObject.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ErrorObject.cs new file mode 100644 index 0000000000..bc37ec172f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ErrorObject.cs @@ -0,0 +1,133 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorObject : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The code property + public string? Code + { + get { return BackingStore?.Get("code"); } + set { BackingStore?.Set("code", value); } + } + + /// The detail property + public string? Detail + { + get { return BackingStore?.Get("detail"); } + set { BackingStore?.Set("detail", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ErrorLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The source property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ErrorSource? Source + { + get { return BackingStore?.Get("source"); } + set { BackingStore?.Set("source", value); } + } + + /// The status property + public string? Status + { + get { return BackingStore?.Get("status"); } + set { BackingStore?.Set("status", value); } + } + + /// The title property + public string? Title + { + get { return BackingStore?.Get("title"); } + set { BackingStore?.Set("title", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorObject() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ErrorObject CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ErrorObject(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "code", n => { Code = n.GetStringValue(); } }, + { "detail", n => { Detail = n.GetStringValue(); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ErrorLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "source", n => { Source = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ErrorSource.CreateFromDiscriminatorValue); } }, + { "status", n => { Status = n.GetStringValue(); } }, + { "title", n => { Title = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("code", Code); + writer.WriteStringValue("detail", Detail); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + writer.WriteObjectValue("source", Source); + writer.WriteStringValue("status", Status); + writer.WriteStringValue("title", Title); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ErrorResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ErrorResponseDocument.cs new file mode 100644 index 0000000000..6510f5a96b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ErrorResponseDocument.cs @@ -0,0 +1,92 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorResponseDocument : ApiException, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The errors property + public List? Errors + { + get { return BackingStore?.Get?>("errors"); } + set { BackingStore?.Set("errors", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ErrorTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The primary error message. + public override string Message { get => base.Message; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ErrorResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ErrorResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "errors", n => { Errors = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ErrorObject.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ErrorTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("errors", Errors); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ErrorSource.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ErrorSource.cs new file mode 100644 index 0000000000..ec82e2fa2d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ErrorSource.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorSource : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The header property + public string? Header + { + get { return BackingStore?.Get("header"); } + set { BackingStore?.Set("header", value); } + } + + /// The parameter property + public string? Parameter + { + get { return BackingStore?.Get("parameter"); } + set { BackingStore?.Set("parameter", value); } + } + + /// The pointer property + public string? Pointer + { + get { return BackingStore?.Get("pointer"); } + set { BackingStore?.Set("pointer", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorSource() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ErrorSource CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ErrorSource(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "header", n => { Header = n.GetStringValue(); } }, + { "parameter", n => { Parameter = n.GetStringValue(); } }, + { "pointer", n => { Pointer = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("header", Header); + writer.WriteStringValue("parameter", Parameter); + writer.WriteStringValue("pointer", Pointer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ErrorTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ErrorTopLevelLinks.cs new file mode 100644 index 0000000000..2cf0cf3b8b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ErrorTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ErrorTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ErrorTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/FamilyHomeIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/FamilyHomeIdentifierInRequest.cs new file mode 100644 index 0000000000..d97a11846a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/FamilyHomeIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class FamilyHomeIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResidenceIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.FamilyHomeIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.FamilyHomeIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/FamilyHomeIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/FamilyHomeIdentifierInResponse.cs new file mode 100644 index 0000000000..8e2679ad47 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/FamilyHomeIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class FamilyHomeIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResidenceIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.FamilyHomeIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.FamilyHomeIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/FamilyHomeResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/FamilyHomeResourceType.cs new file mode 100644 index 0000000000..137d5442b3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/FamilyHomeResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum FamilyHomeResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "familyHomes")] + #pragma warning disable CS1591 + FamilyHomes, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/FamilyHomeRoomsRelationshipIdentifier.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/FamilyHomeRoomsRelationshipIdentifier.cs new file mode 100644 index 0000000000..39c141405a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/FamilyHomeRoomsRelationshipIdentifier.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class FamilyHomeRoomsRelationshipIdentifier : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationship property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.FamilyHomeRoomsRelationshipName? Relationship + { + get { return BackingStore?.Get("relationship"); } + set { BackingStore?.Set("relationship", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.FamilyHomeResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public FamilyHomeRoomsRelationshipIdentifier() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.FamilyHomeRoomsRelationshipIdentifier CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.FamilyHomeRoomsRelationshipIdentifier(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationship", n => { Relationship = n.GetEnumValue(); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteEnumValue("relationship", Relationship); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/FamilyHomeRoomsRelationshipName.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/FamilyHomeRoomsRelationshipName.cs new file mode 100644 index 0000000000..7429d6b60c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/FamilyHomeRoomsRelationshipName.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum FamilyHomeRoomsRelationshipName + #pragma warning restore CS1591 + { + [EnumMember(Value = "rooms")] + #pragma warning disable CS1591 + Rooms, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/IdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/IdentifierInRequest.cs new file mode 100644 index 0000000000..41f6b2aca0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/IdentifierInRequest.cs @@ -0,0 +1,94 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class IdentifierInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public IdentifierInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.IdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.BathroomIdentifierInRequest(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.BedroomIdentifierInRequest(), + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.BuildingIdentifierInRequest(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.FamilyHomeIdentifierInRequest(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.KitchenIdentifierInRequest(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.LivingRoomIdentifierInRequest(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.MansionIdentifierInRequest(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResidenceIdentifierInRequest(), + "rooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomIdentifierInRequest(), + "staffMembers" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.StaffMemberIdentifierInRequest(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToiletIdentifierInRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.IdentifierInRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/KitchenIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/KitchenIdentifierInRequest.cs new file mode 100644 index 0000000000..7da663f22c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/KitchenIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class KitchenIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.KitchenIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.KitchenIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/KitchenIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/KitchenIdentifierInResponse.cs new file mode 100644 index 0000000000..42521bcf2a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/KitchenIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class KitchenIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.KitchenIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.KitchenIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/LivingRoomIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/LivingRoomIdentifierInRequest.cs new file mode 100644 index 0000000000..831828e8ad --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/LivingRoomIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class LivingRoomIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.LivingRoomIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.LivingRoomIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/LivingRoomIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/LivingRoomIdentifierInResponse.cs new file mode 100644 index 0000000000..c4d0e79170 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/LivingRoomIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class LivingRoomIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.LivingRoomIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.LivingRoomIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/MansionIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/MansionIdentifierInRequest.cs new file mode 100644 index 0000000000..bb3e3158a0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/MansionIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class MansionIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResidenceIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.MansionIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.MansionIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/MansionIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/MansionIdentifierInResponse.cs new file mode 100644 index 0000000000..f2d27f433d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/MansionIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class MansionIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResidenceIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.MansionIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.MansionIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/MansionResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/MansionResourceType.cs new file mode 100644 index 0000000000..caf0b5404d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/MansionResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum MansionResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "mansions")] + #pragma warning disable CS1591 + Mansions, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/MansionRoomsRelationshipIdentifier.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/MansionRoomsRelationshipIdentifier.cs new file mode 100644 index 0000000000..b48f1b49c2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/MansionRoomsRelationshipIdentifier.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class MansionRoomsRelationshipIdentifier : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationship property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.MansionRoomsRelationshipName? Relationship + { + get { return BackingStore?.Get("relationship"); } + set { BackingStore?.Set("relationship", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.MansionResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public MansionRoomsRelationshipIdentifier() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.MansionRoomsRelationshipIdentifier CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.MansionRoomsRelationshipIdentifier(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationship", n => { Relationship = n.GetEnumValue(); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteEnumValue("relationship", Relationship); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/MansionRoomsRelationshipName.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/MansionRoomsRelationshipName.cs new file mode 100644 index 0000000000..1a8e469550 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/MansionRoomsRelationshipName.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum MansionRoomsRelationshipName + #pragma warning restore CS1591 + { + [EnumMember(Value = "rooms")] + #pragma warning disable CS1591 + Rooms, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/MansionStaffRelationshipIdentifier.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/MansionStaffRelationshipIdentifier.cs new file mode 100644 index 0000000000..4dfc858ac1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/MansionStaffRelationshipIdentifier.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class MansionStaffRelationshipIdentifier : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationship property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.MansionStaffRelationshipName? Relationship + { + get { return BackingStore?.Get("relationship"); } + set { BackingStore?.Set("relationship", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.MansionResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public MansionStaffRelationshipIdentifier() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.MansionStaffRelationshipIdentifier CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.MansionStaffRelationshipIdentifier(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationship", n => { Relationship = n.GetEnumValue(); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteEnumValue("relationship", Relationship); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/MansionStaffRelationshipName.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/MansionStaffRelationshipName.cs new file mode 100644 index 0000000000..ec44953c88 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/MansionStaffRelationshipName.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum MansionStaffRelationshipName + #pragma warning restore CS1591 + { + [EnumMember(Value = "staff")] + #pragma warning disable CS1591 + Staff, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/Meta.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/Meta.cs new file mode 100644 index 0000000000..1ea6ae9e08 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/Meta.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class Meta : IAdditionalDataHolder, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + public IDictionary AdditionalData + { + get { return BackingStore.Get>("AdditionalData") ?? new Dictionary(); } + set { BackingStore.Set("AdditionalData", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// + /// Instantiates a new and sets the default values. + /// + public Meta() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + AdditionalData = new Dictionary(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteAdditionalData(AdditionalData); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/OperationsRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/OperationsRequestDocument.cs new file mode 100644 index 0000000000..7b082fd130 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/OperationsRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class OperationsRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// The atomicOperations property + public List? AtomicOperations + { + get { return BackingStore?.Get?>("atomic:operations"); } + set { BackingStore?.Set("atomic:operations", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public OperationsRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.OperationsRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.OperationsRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "atomic:operations", n => { AtomicOperations = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AtomicOperation.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("atomic:operations", AtomicOperations); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/OperationsResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/OperationsResponseDocument.cs new file mode 100644 index 0000000000..b0289c2a4d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/OperationsResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class OperationsResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// The atomicResults property + public List? AtomicResults + { + get { return BackingStore?.Get?>("atomic:results"); } + set { BackingStore?.Set("atomic:results", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public OperationsResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.OperationsResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.OperationsResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "atomic:results", n => { AtomicResults = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AtomicResult.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("atomic:results", AtomicResults); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipLinks.cs new file mode 100644 index 0000000000..b46e93f5db --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInBathroomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInBathroomResponse.cs new file mode 100644 index 0000000000..7fee235be0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInBathroomResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInBathroomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInBathroomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInBathroomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInBedroomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInBedroomResponse.cs new file mode 100644 index 0000000000..ad3b9d40cc --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInBedroomResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInBedroomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInBedroomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInBedroomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInBuildingResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInBuildingResponse.cs new file mode 100644 index 0000000000..086834d097 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInBuildingResponse.cs @@ -0,0 +1,57 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInBuildingResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInBuildingResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInFamilyHomeResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInMansionResponse(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInResidenceResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInBuildingResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateBathroomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateBathroomRequest.cs new file mode 100644 index 0000000000..75fc9b1208 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateBathroomRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateBathroomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateBathroomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateBathroomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateBedroomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateBedroomRequest.cs new file mode 100644 index 0000000000..7cab1ca126 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateBedroomRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateBedroomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateBedroomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateBedroomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateBuildingRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateBuildingRequest.cs new file mode 100644 index 0000000000..50a24dcd76 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateBuildingRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateBuildingRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateBuildingRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateBuildingRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateFamilyHomeRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateFamilyHomeRequest.cs new file mode 100644 index 0000000000..bd4c3254f7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateFamilyHomeRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateFamilyHomeRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateFamilyHomeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateFamilyHomeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateKitchenRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateKitchenRequest.cs new file mode 100644 index 0000000000..677c53110f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateKitchenRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateKitchenRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateKitchenRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateKitchenRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateLivingRoomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateLivingRoomRequest.cs new file mode 100644 index 0000000000..a9158cc843 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateLivingRoomRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateLivingRoomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateLivingRoomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateLivingRoomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateMansionRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateMansionRequest.cs new file mode 100644 index 0000000000..77308a0713 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateMansionRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateMansionRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// The staff property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToManyStaffMemberInRequest? Staff + { + get { return BackingStore?.Get("staff"); } + set { BackingStore?.Set("staff", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateMansionRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateMansionRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "staff", n => { Staff = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToManyStaffMemberInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("staff", Staff); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateRequest.cs new file mode 100644 index 0000000000..745beda79a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateRequest.cs @@ -0,0 +1,84 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateBathroomRequest(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateBedroomRequest(), + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateBuildingRequest(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateFamilyHomeRequest(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateKitchenRequest(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateLivingRoomRequest(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateMansionRequest(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateResidenceRequest(), + "rooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateRoomRequest(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateToiletRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateResidenceRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateResidenceRequest.cs new file mode 100644 index 0000000000..b6eab58938 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateResidenceRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateResidenceRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateBuildingRequest, IParsable + #pragma warning restore CS1591 + { + /// The rooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToManyRoomInRequest? Rooms + { + get { return BackingStore?.Get("rooms"); } + set { BackingStore?.Set("rooms", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateResidenceRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateResidenceRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "rooms", n => { Rooms = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToManyRoomInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("rooms", Rooms); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateRoomRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateRoomRequest.cs new file mode 100644 index 0000000000..3f2865ba35 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateRoomRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateRoomRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToOneResidenceInRequest? Residence + { + get { return BackingStore?.Get("residence"); } + set { BackingStore?.Set("residence", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateRoomRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateRoomRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "residence", n => { Residence = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToOneResidenceInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("residence", Residence); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateToiletRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateToiletRequest.cs new file mode 100644 index 0000000000..606836ab3d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInCreateToiletRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateToiletRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateRoomRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateToiletRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInCreateToiletRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInFamilyHomeResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInFamilyHomeResponse.cs new file mode 100644 index 0000000000..ad5618acc3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInFamilyHomeResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInFamilyHomeResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInResidenceResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInFamilyHomeResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInFamilyHomeResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInKitchenResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInKitchenResponse.cs new file mode 100644 index 0000000000..58ef29ab15 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInKitchenResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInKitchenResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInKitchenResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInKitchenResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInLivingRoomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInLivingRoomResponse.cs new file mode 100644 index 0000000000..0e1b08055a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInLivingRoomResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInLivingRoomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInLivingRoomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInLivingRoomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInMansionResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInMansionResponse.cs new file mode 100644 index 0000000000..f34735a430 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInMansionResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInMansionResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInResidenceResponse, IParsable + #pragma warning restore CS1591 + { + /// The staff property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToManyStaffMemberInResponse? Staff + { + get { return BackingStore?.Get("staff"); } + set { BackingStore?.Set("staff", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInMansionResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInMansionResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "staff", n => { Staff = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToManyStaffMemberInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("staff", Staff); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInResidenceResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInResidenceResponse.cs new file mode 100644 index 0000000000..4f3e9acd8b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInResidenceResponse.cs @@ -0,0 +1,65 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInResidenceResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInBuildingResponse, IParsable + #pragma warning restore CS1591 + { + /// The rooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToManyRoomInResponse? Rooms + { + get { return BackingStore?.Get("rooms"); } + set { BackingStore?.Set("rooms", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInResidenceResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInFamilyHomeResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInMansionResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInResidenceResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "rooms", n => { Rooms = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToManyRoomInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("rooms", Rooms); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInResponse.cs new file mode 100644 index 0000000000..071fede4a7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInResponse.cs @@ -0,0 +1,84 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInBathroomResponse(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInBedroomResponse(), + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInBuildingResponse(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInFamilyHomeResponse(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInKitchenResponse(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInLivingRoomResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInMansionResponse(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInResidenceResponse(), + "rooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInRoomResponse(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInToiletResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInRoomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInRoomResponse.cs new file mode 100644 index 0000000000..16c3c2ea1f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInRoomResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInRoomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToOneResidenceInResponse? Residence + { + get { return BackingStore?.Get("residence"); } + set { BackingStore?.Set("residence", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInRoomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInBathroomResponse(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInBedroomResponse(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInKitchenResponse(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInLivingRoomResponse(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInToiletResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInRoomResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "residence", n => { Residence = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToOneResidenceInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("residence", Residence); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInToiletResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInToiletResponse.cs new file mode 100644 index 0000000000..55e9808d2b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInToiletResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInToiletResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInToiletResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInToiletResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInUpdateBuildingRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInUpdateBuildingRequest.cs new file mode 100644 index 0000000000..e085a94a4c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInUpdateBuildingRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateBuildingRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInUpdateBuildingRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInUpdateBuildingRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInUpdateFamilyHomeRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInUpdateFamilyHomeRequest.cs new file mode 100644 index 0000000000..ba2117d3ac --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInUpdateFamilyHomeRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateFamilyHomeRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInUpdateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInUpdateFamilyHomeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInUpdateFamilyHomeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInUpdateMansionRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInUpdateMansionRequest.cs new file mode 100644 index 0000000000..ec72193d54 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInUpdateMansionRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateMansionRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInUpdateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// The staff property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToManyStaffMemberInRequest? Staff + { + get { return BackingStore?.Get("staff"); } + set { BackingStore?.Set("staff", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInUpdateMansionRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInUpdateMansionRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "staff", n => { Staff = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToManyStaffMemberInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("staff", Staff); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInUpdateRequest.cs new file mode 100644 index 0000000000..f27b90a2cf --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInUpdateRequest.cs @@ -0,0 +1,78 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInUpdateBuildingRequest(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInUpdateFamilyHomeRequest(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInUpdateMansionRequest(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInUpdateResidenceRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInUpdateResidenceRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInUpdateResidenceRequest.cs new file mode 100644 index 0000000000..0188f28d4a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RelationshipsInUpdateResidenceRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateResidenceRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInUpdateBuildingRequest, IParsable + #pragma warning restore CS1591 + { + /// The rooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToManyRoomInRequest? Rooms + { + get { return BackingStore?.Get("rooms"); } + set { BackingStore?.Set("rooms", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInUpdateResidenceRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipsInUpdateResidenceRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "rooms", n => { Rooms = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToManyRoomInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("rooms", Rooms); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RemoveFromMansionRoomsRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RemoveFromMansionRoomsRelationshipOperation.cs new file mode 100644 index 0000000000..8fa3b08883 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RemoveFromMansionRoomsRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RemoveFromMansionRoomsRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RemoveOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.MansionRoomsRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RemoveFromMansionRoomsRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RemoveFromMansionRoomsRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.MansionRoomsRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RemoveFromMansionStaffRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RemoveFromMansionStaffRelationshipOperation.cs new file mode 100644 index 0000000000..80ab4892b3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RemoveFromMansionStaffRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RemoveFromMansionStaffRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RemoveOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.MansionStaffRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RemoveFromMansionStaffRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RemoveFromMansionStaffRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.StaffMemberIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.MansionStaffRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RemoveOperationCode.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RemoveOperationCode.cs new file mode 100644 index 0000000000..aba5993194 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RemoveOperationCode.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum RemoveOperationCode + #pragma warning restore CS1591 + { + [EnumMember(Value = "remove")] + #pragma warning disable CS1591 + Remove, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResidenceIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResidenceIdentifierInRequest.cs new file mode 100644 index 0000000000..893c562a14 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResidenceIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResidenceIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.BuildingIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResidenceIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResidenceIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResidenceIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResidenceIdentifierInResponse.cs new file mode 100644 index 0000000000..934cf9c434 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResidenceIdentifierInResponse.cs @@ -0,0 +1,56 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResidenceIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.BuildingIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResidenceIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.FamilyHomeIdentifierInResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.MansionIdentifierInResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResidenceIdentifierInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResourceInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResourceInCreateRequest.cs new file mode 100644 index 0000000000..7f596adfe4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResourceInCreateRequest.cs @@ -0,0 +1,93 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateBathroomRequest(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateBedroomRequest(), + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateBuildingRequest(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateFamilyHomeRequest(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateKitchenRequest(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateLivingRoomRequest(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateMansionRequest(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateResidenceRequest(), + "rooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateRoomRequest(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInCreateToiletRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResourceInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResourceInResponse.cs new file mode 100644 index 0000000000..9476d7c9a4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResourceInResponse.cs @@ -0,0 +1,93 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInBathroomResponse(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInBedroomResponse(), + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInBuildingResponse(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInFamilyHomeResponse(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInKitchenResponse(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInLivingRoomResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInMansionResponse(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInResidenceResponse(), + "rooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInRoomResponse(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInToiletResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResourceInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResourceInUpdateRequest.cs new file mode 100644 index 0000000000..f9fc29941b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResourceInUpdateRequest.cs @@ -0,0 +1,87 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInUpdateBuildingRequest(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInUpdateFamilyHomeRequest(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInUpdateMansionRequest(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInUpdateResidenceRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResourceLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResourceLinks.cs new file mode 100644 index 0000000000..ee38acc9b8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResourceLinks.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResourceTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResourceTopLevelLinks.cs new file mode 100644 index 0000000000..fd38a0604f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResourceTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResourceTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResourceType.cs new file mode 100644 index 0000000000..b5b42b8b81 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ResourceType.cs @@ -0,0 +1,58 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum ResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "bathrooms")] + #pragma warning disable CS1591 + Bathrooms, + #pragma warning restore CS1591 + [EnumMember(Value = "bedrooms")] + #pragma warning disable CS1591 + Bedrooms, + #pragma warning restore CS1591 + [EnumMember(Value = "buildings")] + #pragma warning disable CS1591 + Buildings, + #pragma warning restore CS1591 + [EnumMember(Value = "familyHomes")] + #pragma warning disable CS1591 + FamilyHomes, + #pragma warning restore CS1591 + [EnumMember(Value = "kitchens")] + #pragma warning disable CS1591 + Kitchens, + #pragma warning restore CS1591 + [EnumMember(Value = "livingRooms")] + #pragma warning disable CS1591 + LivingRooms, + #pragma warning restore CS1591 + [EnumMember(Value = "mansions")] + #pragma warning disable CS1591 + Mansions, + #pragma warning restore CS1591 + [EnumMember(Value = "residences")] + #pragma warning disable CS1591 + Residences, + #pragma warning restore CS1591 + [EnumMember(Value = "rooms")] + #pragma warning disable CS1591 + Rooms, + #pragma warning restore CS1591 + [EnumMember(Value = "staffMembers")] + #pragma warning disable CS1591 + StaffMembers, + #pragma warning restore CS1591 + [EnumMember(Value = "toilets")] + #pragma warning disable CS1591 + Toilets, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RoomIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RoomIdentifierInRequest.cs new file mode 100644 index 0000000000..021f76a3a6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RoomIdentifierInRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RoomIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RoomIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RoomIdentifierInResponse.cs new file mode 100644 index 0000000000..60a3ac6234 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RoomIdentifierInResponse.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RoomIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RoomIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.BathroomIdentifierInResponse(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.BedroomIdentifierInResponse(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.KitchenIdentifierInResponse(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.LivingRoomIdentifierInResponse(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToiletIdentifierInResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomIdentifierInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RoomResidenceRelationshipIdentifier.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RoomResidenceRelationshipIdentifier.cs new file mode 100644 index 0000000000..73755a5e9e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RoomResidenceRelationshipIdentifier.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RoomResidenceRelationshipIdentifier : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// The relationship property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomResidenceRelationshipName? Relationship + { + get { return BackingStore?.Get("relationship"); } + set { BackingStore?.Set("relationship", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RoomResidenceRelationshipIdentifier() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomResidenceRelationshipIdentifier CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomResidenceRelationshipIdentifier(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + { "relationship", n => { Relationship = n.GetEnumValue(); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + writer.WriteEnumValue("relationship", Relationship); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RoomResidenceRelationshipName.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RoomResidenceRelationshipName.cs new file mode 100644 index 0000000000..b10e9bf6df --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RoomResidenceRelationshipName.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum RoomResidenceRelationshipName + #pragma warning restore CS1591 + { + [EnumMember(Value = "residence")] + #pragma warning disable CS1591 + Residence, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RoomResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RoomResourceType.cs new file mode 100644 index 0000000000..b9aff9a41e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/RoomResourceType.cs @@ -0,0 +1,34 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum RoomResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "bathrooms")] + #pragma warning disable CS1591 + Bathrooms, + #pragma warning restore CS1591 + [EnumMember(Value = "bedrooms")] + #pragma warning disable CS1591 + Bedrooms, + #pragma warning restore CS1591 + [EnumMember(Value = "kitchens")] + #pragma warning disable CS1591 + Kitchens, + #pragma warning restore CS1591 + [EnumMember(Value = "livingRooms")] + #pragma warning disable CS1591 + LivingRooms, + #pragma warning restore CS1591 + [EnumMember(Value = "toilets")] + #pragma warning disable CS1591 + Toilets, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/StaffMemberIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/StaffMemberIdentifierInRequest.cs new file mode 100644 index 0000000000..25b9db0424 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/StaffMemberIdentifierInRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class StaffMemberIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The lid property + public string? Lid + { + get { return BackingStore?.Get("lid"); } + set { BackingStore?.Set("lid", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.StaffMemberIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.StaffMemberIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + { "lid", n => { Lid = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + writer.WriteStringValue("lid", Lid); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/StaffMemberIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/StaffMemberIdentifierInResponse.cs new file mode 100644 index 0000000000..a6ef6ac879 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/StaffMemberIdentifierInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class StaffMemberIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.StaffMemberResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public StaffMemberIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.StaffMemberIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.StaffMemberIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/StaffMemberResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/StaffMemberResourceType.cs new file mode 100644 index 0000000000..7dbd4afb02 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/StaffMemberResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum StaffMemberResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "staffMembers")] + #pragma warning disable CS1591 + StaffMembers, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToManyRoomInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToManyRoomInRequest.cs new file mode 100644 index 0000000000..352d3e295b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToManyRoomInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyRoomInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyRoomInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToManyRoomInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToManyRoomInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToManyRoomInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToManyRoomInResponse.cs new file mode 100644 index 0000000000..8800c48c80 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToManyRoomInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyRoomInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyRoomInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToManyRoomInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToManyRoomInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToManyStaffMemberInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToManyStaffMemberInRequest.cs new file mode 100644 index 0000000000..94cc664f89 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToManyStaffMemberInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyStaffMemberInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyStaffMemberInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToManyStaffMemberInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToManyStaffMemberInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.StaffMemberIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToManyStaffMemberInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToManyStaffMemberInResponse.cs new file mode 100644 index 0000000000..1e0521601c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToManyStaffMemberInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyStaffMemberInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyStaffMemberInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToManyStaffMemberInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToManyStaffMemberInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.StaffMemberIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToOneResidenceInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToOneResidenceInRequest.cs new file mode 100644 index 0000000000..132fca3262 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToOneResidenceInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToOneResidenceInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResidenceIdentifierInRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToOneResidenceInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToOneResidenceInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToOneResidenceInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResidenceIdentifierInRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToOneResidenceInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToOneResidenceInResponse.cs new file mode 100644 index 0000000000..258a4c16eb --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToOneResidenceInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToOneResidenceInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResidenceIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToOneResidenceInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToOneResidenceInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToOneResidenceInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResidenceIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToiletIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToiletIdentifierInRequest.cs new file mode 100644 index 0000000000..f02b763d60 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToiletIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToiletIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToiletIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToiletIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToiletIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToiletIdentifierInResponse.cs new file mode 100644 index 0000000000..7b02759616 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/ToiletIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToiletIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToiletIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ToiletIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateBathroomResidenceRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateBathroomResidenceRelationshipOperation.cs new file mode 100644 index 0000000000..37aeb3e0fd --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateBathroomResidenceRelationshipOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateBathroomResidenceRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateRoomResidenceRelationshipOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateBathroomResidenceRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateBathroomResidenceRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateBedroomResidenceRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateBedroomResidenceRelationshipOperation.cs new file mode 100644 index 0000000000..96fa8dc04e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateBedroomResidenceRelationshipOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateBedroomResidenceRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateRoomResidenceRelationshipOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateBedroomResidenceRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateBedroomResidenceRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateFamilyHomeOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateFamilyHomeOperation.cs new file mode 100644 index 0000000000..23ce1283ae --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateFamilyHomeOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateFamilyHomeOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateResidenceOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateFamilyHomeOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateFamilyHomeOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateKitchenResidenceRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateKitchenResidenceRelationshipOperation.cs new file mode 100644 index 0000000000..0feb395978 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateKitchenResidenceRelationshipOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateKitchenResidenceRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateRoomResidenceRelationshipOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateKitchenResidenceRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateKitchenResidenceRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateLivingRoomResidenceRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateLivingRoomResidenceRelationshipOperation.cs new file mode 100644 index 0000000000..eb085bde37 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateLivingRoomResidenceRelationshipOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateLivingRoomResidenceRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateRoomResidenceRelationshipOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateLivingRoomResidenceRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateLivingRoomResidenceRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateMansionOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateMansionOperation.cs new file mode 100644 index 0000000000..0e9c20fc91 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateMansionOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateMansionOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateResidenceOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateMansionOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateMansionOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateOperationCode.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateOperationCode.cs new file mode 100644 index 0000000000..44e69148e2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateOperationCode.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum UpdateOperationCode + #pragma warning restore CS1591 + { + [EnumMember(Value = "update")] + #pragma warning disable CS1591 + Update, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateResidenceOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateResidenceOperation.cs new file mode 100644 index 0000000000..b14a3e002b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateResidenceOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateResidenceOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInUpdateResidenceRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResidenceIdentifierInRequest? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateResidenceOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateResidenceOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.DataInUpdateResidenceRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResidenceIdentifierInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateRoomResidenceRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateRoomResidenceRelationshipOperation.cs new file mode 100644 index 0000000000..5e9d650f72 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateRoomResidenceRelationshipOperation.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateRoomResidenceRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.AtomicOperation, IParsable + #pragma warning restore CS1591 + { + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResidenceIdentifierInRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The op property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateOperationCode? Op + { + get { return BackingStore?.Get("op"); } + set { BackingStore?.Set("op", value); } + } + + /// The ref property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomResidenceRelationshipIdentifier? Ref + { + get { return BackingStore?.Get("ref"); } + set { BackingStore?.Set("ref", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateRoomResidenceRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateRoomResidenceRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ResidenceIdentifierInRequest.CreateFromDiscriminatorValue); } }, + { "op", n => { Op = n.GetEnumValue(); } }, + { "ref", n => { Ref = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.RoomResidenceRelationshipIdentifier.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("data", Data); + writer.WriteEnumValue("op", Op); + writer.WriteObjectValue("ref", Ref); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateToiletResidenceRelationshipOperation.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateToiletResidenceRelationshipOperation.cs new file mode 100644 index 0000000000..18fc32b6d4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Models/UpdateToiletResidenceRelationshipOperation.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateToiletResidenceRelationshipOperation : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateRoomResidenceRelationshipOperation, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateToiletResidenceRelationshipOperation CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.UpdateToiletResidenceRelationshipOperation(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Operations/OperationsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Operations/OperationsRequestBuilder.cs new file mode 100644 index 0000000000..32b762f738 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/Operations/OperationsRequestBuilder.cs @@ -0,0 +1,94 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Operations +{ + /// + /// Builds and executes requests for operations under \operations + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class OperationsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public OperationsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/operations", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public OperationsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/operations", rawUrl) + { + } + + /// + /// Performs multiple mutations in a linear and atomic manner. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.OperationsRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.OperationsResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Performs multiple mutations in a linear and atomic manner. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models.OperationsRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=atomic;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=atomic;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Operations.OperationsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Operations.OperationsRequestBuilder(rawUrl, RequestAdapter); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/SubsetOfOperationsInheritanceClient.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/SubsetOfOperationsInheritanceClient.cs new file mode 100644 index 0000000000..f5764b4205 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/SubsetOfOperationsInheritanceClient.cs @@ -0,0 +1,54 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using Microsoft.Kiota.Serialization.Form; +using Microsoft.Kiota.Serialization.Json; +using Microsoft.Kiota.Serialization.Multipart; +using Microsoft.Kiota.Serialization.Text; +using OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Operations; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode +{ + /// + /// The main entry point of the SDK, exposes the configuration and the fluent API. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class SubsetOfOperationsInheritanceClient : BaseRequestBuilder + { + /// The operations property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Operations.OperationsRequestBuilder Operations + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Operations.OperationsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The backing store to use for the models. + /// The request adapter to use to execute the requests. + public SubsetOfOperationsInheritanceClient(IRequestAdapter requestAdapter, IBackingStoreFactory backingStore = default) : base(requestAdapter, "{+baseurl}", new Dictionary()) + { + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + if (string.IsNullOrEmpty(RequestAdapter.BaseUrl)) + { + RequestAdapter.BaseUrl = "http://localhost"; + } + PathParameters.TryAdd("baseurl", RequestAdapter.BaseUrl); + RequestAdapter.EnableBackingStore(backingStore); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/OperationsInheritanceTests.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/OperationsInheritanceTests.cs new file mode 100644 index 0000000000..3acddac8f6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/OperationsInheritanceTests.cs @@ -0,0 +1,352 @@ +using System.Net; +using FluentAssertions; +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.Resources; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode; +using OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.ResourceInheritance; +using OpenApiTests.ResourceInheritance.Models; +using OpenApiTests.ResourceInheritance.SubsetOfOperations; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations; + +public sealed class OperationsInheritanceTests + : IClassFixture, ResourceInheritanceDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, ResourceInheritanceDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly ResourceInheritanceFakers _fakers = new(); + + public OperationsInheritanceTests(IntegrationTestContext, ResourceInheritanceDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseInheritanceControllers(true); + + testContext.ConfigureServices(services => + { + services.AddScoped(typeof(IResourceChangeTracker<>), typeof(NeverSameResourceChangeTracker<>)); + + services.AddSingleton(); + services.AddSingleton(); + }); + } + + [Fact] + public async Task Can_use_inheritance_at_operations_endpoint() + { + // Arrange + StaffMember existingStaffMember = _fakers.StaffMember.GenerateOne(); + + Mansion newMansion = _fakers.Mansion.GenerateOne(); + Kitchen newKitchen = _fakers.Kitchen.GenerateOne(); + FamilyHome newFamilyHome = _fakers.FamilyHome.GenerateOne(); + Bedroom newBedroom = _fakers.Bedroom.GenerateOne(); + int? newFamilyHomeSurfaceInSquareMeters = _fakers.FamilyHome.GenerateOne().SurfaceInSquareMeters; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.StaffMembers.Add(existingStaffMember); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new SubsetOfOperationsInheritanceClient(requestAdapter); + + const string mansionLid = "mansion-lid"; + const string kitchenLid = "kitchen-lid"; + const string familyHomeLid = "family-home-lid"; + const string bedroomLid = "bedroom-lid"; + + OperationsRequestDocument requestBody = new() + { + AtomicOperations = + [ + // NOTE: CreateBuildingOperation is not generated, because it is turned off. + new CreateResidenceOperation + { + Op = AddOperationCode.Add, + Data = new DataInCreateMansionRequest + { + Type = ResourceType.Mansions, + Lid = mansionLid, + Attributes = new AttributesInCreateMansionRequest + { + SurfaceInSquareMeters = newMansion.SurfaceInSquareMeters!.Value, + NumberOfResidents = newMansion.NumberOfResidents!.Value, + OwnerName = newMansion.OwnerName + }, + Relationships = new RelationshipsInCreateMansionRequest + { + Staff = new ToManyStaffMemberInRequest + { + Data = + [ + new StaffMemberIdentifierInRequest + { + Type = ResourceType.StaffMembers, + Id = existingStaffMember.StringId + } + ] + } + } + } + }, + // NOTE: It is possible to create an operation for abstract type. + new CreateRoomOperation + { + Op = AddOperationCode.Add, + // NOTE: DataInCreateRoomRequest is generated, but as abstract type. + Data = new DataInCreateKitchenRequest + { + Type = ResourceType.Kitchens, + Lid = kitchenLid, + Attributes = new AttributesInCreateKitchenRequest + { + SurfaceInSquareMeters = newKitchen.SurfaceInSquareMeters!.Value, + HasPantry = newKitchen.HasPantry!.Value + }, + Relationships = new RelationshipsInCreateKitchenRequest + { + Residence = new ToOneResidenceInRequest + { + Data = new MansionIdentifierInRequest + { + Type = ResourceType.Mansions, + Lid = mansionLid + } + } + } + } + }, + new CreateFamilyHomeOperation + { + Op = AddOperationCode.Add, + Data = new DataInCreateFamilyHomeRequest + { + Type = ResourceType.FamilyHomes, + Lid = familyHomeLid, + Attributes = new AttributesInCreateFamilyHomeRequest + { + SurfaceInSquareMeters = newFamilyHome.SurfaceInSquareMeters!.Value, + NumberOfResidents = newFamilyHome.NumberOfResidents!.Value, + FloorCount = newFamilyHome.FloorCount + } + } + }, + new CreateBedroomOperation + { + Op = AddOperationCode.Add, + Data = new DataInCreateBedroomRequest + { + Type = ResourceType.Bedrooms, + Lid = bedroomLid, + Attributes = new AttributesInCreateBedroomRequest + { + SurfaceInSquareMeters = newBedroom.SurfaceInSquareMeters!.Value, + BedCount = newBedroom.BedCount!.Value + }, + Relationships = new RelationshipsInCreateBedroomRequest + { + Residence = new ToOneResidenceInRequest + { + Data = new FamilyHomeIdentifierInRequest + { + Type = ResourceType.FamilyHomes, + Lid = familyHomeLid + } + } + } + } + }, + new AddToFamilyHomeRoomsRelationshipOperation + { + Op = AddOperationCode.Add, + Ref = new FamilyHomeRoomsRelationshipIdentifier + { + Type = FamilyHomeResourceType.FamilyHomes, + Relationship = FamilyHomeRoomsRelationshipName.Rooms, + Lid = familyHomeLid + }, + Data = + [ + new KitchenIdentifierInRequest + { + Type = ResourceType.Kitchens, + Lid = kitchenLid + } + ] + }, + new UpdateResidenceOperation + { + Op = UpdateOperationCode.Update, + // NOTE: Can use Ref to base type, while Data is derived. + Ref = new ResidenceIdentifierInRequest + { + Type = ResourceType.Residences, + Lid = familyHomeLid + }, + Data = new DataInUpdateFamilyHomeRequest + { + Type = ResourceType.FamilyHomes, + Lid = familyHomeLid, + Attributes = new AttributesInUpdateFamilyHomeRequest + { + SurfaceInSquareMeters = newFamilyHomeSurfaceInSquareMeters + } + } + }, + new RemoveFromMansionStaffRelationshipOperation + { + Op = RemoveOperationCode.Remove, + Ref = new MansionStaffRelationshipIdentifier + { + Type = MansionResourceType.Mansions, + Relationship = MansionStaffRelationshipName.Staff, + Lid = mansionLid + }, + Data = [] + } + ] + }; + + // Act + OperationsResponseDocument? response = await apiClient.Operations.PostAsync(requestBody); + + // Assert + response.Should().NotBeNull(); + response.AtomicResults.Should().HaveCount(7); + + DataInMansionResponse mansionData = response.AtomicResults.ElementAt(0).Data.Should().BeOfType().Subject; + AttributesInMansionResponse mansionAttributes = mansionData.Attributes.Should().BeOfType().Subject; + mansionAttributes.SurfaceInSquareMeters.Should().Be(newMansion.SurfaceInSquareMeters); + mansionAttributes.NumberOfResidents.Should().Be(newMansion.NumberOfResidents); + mansionAttributes.OwnerName.Should().Be(newMansion.OwnerName); + mansionData.Relationships.Should().BeNull(); + + DataInKitchenResponse kitchenData = response.AtomicResults.ElementAt(1).Data.Should().BeOfType().Subject; + AttributesInKitchenResponse kitchenAttributes = kitchenData.Attributes.Should().BeOfType().Subject; + kitchenAttributes.SurfaceInSquareMeters.Should().Be(newKitchen.SurfaceInSquareMeters); + kitchenAttributes.HasPantry.Should().Be(newKitchen.HasPantry); + kitchenData.Relationships.Should().BeNull(); + + DataInFamilyHomeResponse familyHomeData2 = response.AtomicResults.ElementAt(2).Data.Should().BeOfType().Subject; + AttributesInFamilyHomeResponse familyHomeAttributes2 = familyHomeData2.Attributes.Should().BeOfType().Subject; + familyHomeAttributes2.SurfaceInSquareMeters.Should().Be(newFamilyHome.SurfaceInSquareMeters); + familyHomeAttributes2.NumberOfResidents.Should().Be(newFamilyHome.NumberOfResidents); + familyHomeAttributes2.FloorCount.Should().Be(newFamilyHome.FloorCount); + familyHomeData2.Relationships.Should().BeNull(); + + DataInBedroomResponse bedroomData = response.AtomicResults.ElementAt(3).Data.Should().BeOfType().Subject; + AttributesInBedroomResponse bedroomAttributes = bedroomData.Attributes.Should().BeOfType().Subject; + bedroomAttributes.SurfaceInSquareMeters.Should().Be(newBedroom.SurfaceInSquareMeters); + bedroomAttributes.BedCount.Should().Be(newBedroom.BedCount); + bedroomData.Relationships.Should().BeNull(); + + response.AtomicResults.ElementAt(4).Data.Should().BeNull(); + + DataInFamilyHomeResponse familyHomeData5 = response.AtomicResults.ElementAt(5).Data.Should().BeOfType().Subject; + AttributesInFamilyHomeResponse familyHomeAttributes5 = familyHomeData5.Attributes.Should().BeOfType().Subject; + familyHomeAttributes5.SurfaceInSquareMeters.Should().Be(newFamilyHomeSurfaceInSquareMeters); + familyHomeAttributes5.NumberOfResidents.Should().Be(newFamilyHome.NumberOfResidents); + familyHomeAttributes5.FloorCount.Should().Be(newFamilyHome.FloorCount); + familyHomeData5.Relationships.Should().BeNull(); + + response.AtomicResults.ElementAt(6).Data.Should().BeNull(); + + long newMansionId = long.Parse(mansionData.Id.Should().NotBeNull().And.Subject); + long newKitchenId = long.Parse(kitchenData.Id.Should().NotBeNull().And.Subject); + long newFamilyHomeId = long.Parse(familyHomeData2.Id.Should().NotBeNull().And.Subject); + long newBedroomId = long.Parse(bedroomData.Id.Should().NotBeNull().And.Subject); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Mansion mansionInDatabase = + await dbContext.Mansions.Include(mansion => mansion.Rooms).Include(mansion => mansion.Staff).FirstWithIdAsync(newMansionId); + + mansionInDatabase.SurfaceInSquareMeters.Should().Be(newMansion.SurfaceInSquareMeters); + mansionInDatabase.NumberOfResidents.Should().Be(newMansion.NumberOfResidents); + mansionInDatabase.OwnerName.Should().Be(newMansion.OwnerName); + + mansionInDatabase.Rooms.Should().BeEmpty(); + mansionInDatabase.Staff.Should().HaveCount(1); + mansionInDatabase.Staff.ElementAt(0).Id.Should().Be(existingStaffMember.Id); + + FamilyHome familyHomeInDatabase = await dbContext.FamilyHomes.Include(familyHome => familyHome.Rooms).FirstWithIdAsync(newFamilyHomeId); + + familyHomeInDatabase.SurfaceInSquareMeters.Should().Be(newFamilyHomeSurfaceInSquareMeters); + familyHomeInDatabase.NumberOfResidents.Should().Be(newFamilyHome.NumberOfResidents); + familyHomeInDatabase.FloorCount.Should().Be(newFamilyHome.FloorCount); + + familyHomeInDatabase.Rooms.Should().HaveCount(2); + familyHomeInDatabase.Rooms.OfType().Should().ContainSingle(kitchen => kitchen.Id == newKitchenId); + familyHomeInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == newBedroomId); + }); + } + + [Fact] + public async Task Cannot_use_base_attributes_type_in_derived_data() + { + // Arrange + int newFamilyHomeSurfaceInSquareMeters = _fakers.FamilyHome.GenerateOne().SurfaceInSquareMeters!.Value; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new SubsetOfOperationsInheritanceClient(requestAdapter); + + OperationsRequestDocument requestBody = new() + { + AtomicOperations = + [ + new CreateResidenceOperation + { + Op = AddOperationCode.Add, + Data = new DataInCreateFamilyHomeRequest + { + Type = ResourceType.FamilyHomes, + Attributes = new AttributesInCreateResidenceRequest + { + OpenapiDiscriminator = ResourceType.Residences, + SurfaceInSquareMeters = newFamilyHomeSurfaceInSquareMeters + } + } + } + ] + }; + + // Act + Func action = async () => await apiClient.Operations.PostAsync(requestBody); + + // Assert + ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync()).Which; + exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.Conflict); + exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown."); + exception.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Errors.ElementAt(0); + error.Status.Should().Be("409"); + error.Title.Should().Be("Incompatible resource type found."); + error.Detail.Should().Be("Expected openapi:discriminator with value 'familyHomes' instead of 'residences'."); + error.Source.Should().NotBeNull(); + error.Source.Pointer.Should().Be("/atomic:operations[0]/data/attributes/openapi:discriminator"); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Buildings/BuildingsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Buildings/BuildingsRequestBuilder.cs new file mode 100644 index 0000000000..07391862b9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Buildings/BuildingsRequestBuilder.cs @@ -0,0 +1,119 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Buildings.Item; +using OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Buildings +{ + /// + /// Builds and executes requests for operations under \buildings + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BuildingsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.buildings.item collection + /// The identifier of the building to update. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Buildings.Item.BuildingsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Buildings.Item.BuildingsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public BuildingsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/buildings{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public BuildingsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/buildings{?query*}", rawUrl) + { + } + + /// + /// Creates a new building. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.CreateBuildingRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.PrimaryBuildingResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new building. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.CreateBuildingRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Buildings.BuildingsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Buildings.BuildingsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Creates a new building. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BuildingsRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Buildings/Item/BuildingsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Buildings/Item/BuildingsItemRequestBuilder.cs new file mode 100644 index 0000000000..246d250d5a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Buildings/Item/BuildingsItemRequestBuilder.cs @@ -0,0 +1,103 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Buildings.Item +{ + /// + /// Builds and executes requests for operations under \buildings\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BuildingsItemRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public BuildingsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/buildings/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public BuildingsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/buildings/{id}{?query*}", rawUrl) + { + } + + /// + /// Updates an existing building. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.UpdateBuildingRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.PrimaryBuildingResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing building. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.UpdateBuildingRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Buildings.Item.BuildingsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Buildings.Item.BuildingsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Updates an existing building. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class BuildingsItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/CyclePaths/CyclePathsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/CyclePaths/CyclePathsRequestBuilder.cs new file mode 100644 index 0000000000..669dfa603d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/CyclePaths/CyclePathsRequestBuilder.cs @@ -0,0 +1,52 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.CyclePaths.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.CyclePaths +{ + /// + /// Builds and executes requests for operations under \cyclePaths + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class CyclePathsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.cyclePaths.item collection + /// The identifier of the cyclePath to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.CyclePaths.Item.CyclePathsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.CyclePaths.Item.CyclePathsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public CyclePathsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/cyclePaths", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public CyclePathsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/cyclePaths", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/CyclePaths/Item/CyclePathsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/CyclePaths/Item/CyclePathsItemRequestBuilder.cs new file mode 100644 index 0000000000..c66722264f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/CyclePaths/Item/CyclePathsItemRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.CyclePaths.Item +{ + /// + /// Builds and executes requests for operations under \cyclePaths\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class CyclePathsItemRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public CyclePathsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/cyclePaths/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public CyclePathsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/cyclePaths/{id}{?query*}", rawUrl) + { + } + + /// + /// Retrieves an individual cyclePath by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.PrimaryCyclePathResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual cyclePath by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.CyclePaths.Item.CyclePathsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.CyclePaths.Item.CyclePathsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual cyclePath by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class CyclePathsItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class CyclePathsItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Districts/DistrictsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Districts/DistrictsRequestBuilder.cs new file mode 100644 index 0000000000..02116844d5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Districts/DistrictsRequestBuilder.cs @@ -0,0 +1,126 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Districts +{ + /// + /// Builds and executes requests for operations under \districts + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class DistrictsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public DistrictsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public DistrictsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/districts{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of districts. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DistrictCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of districts. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Districts.DistrictsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Districts.DistrictsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of districts. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class DistrictsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class DistrictsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/FamilyHomes/FamilyHomesRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/FamilyHomes/FamilyHomesRequestBuilder.cs new file mode 100644 index 0000000000..162c733ba3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/FamilyHomes/FamilyHomesRequestBuilder.cs @@ -0,0 +1,52 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.FamilyHomes.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.FamilyHomes +{ + /// + /// Builds and executes requests for operations under \familyHomes + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class FamilyHomesRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.familyHomes.item collection + /// The identifier of the familyHome whose related room identities to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.FamilyHomes.Item.FamilyHomesItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.FamilyHomes.Item.FamilyHomesItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public FamilyHomesRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public FamilyHomesRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/FamilyHomes/Item/FamilyHomesItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/FamilyHomes/Item/FamilyHomesItemRequestBuilder.cs new file mode 100644 index 0000000000..d49a39c758 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/FamilyHomes/Item/FamilyHomesItemRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.FamilyHomes.Item.Relationships; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.FamilyHomes.Item +{ + /// + /// Builds and executes requests for operations under \familyHomes\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class FamilyHomesItemRequestBuilder : BaseRequestBuilder + { + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.FamilyHomes.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.FamilyHomes.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public FamilyHomesItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes/{id}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public FamilyHomesItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes/{id}", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/FamilyHomes/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/FamilyHomes/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..e8ffc0c1f4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/FamilyHomes/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.FamilyHomes.Item.Relationships.Rooms; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.FamilyHomes.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \familyHomes\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The rooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.FamilyHomes.Item.Relationships.Rooms.RoomsRequestBuilder Rooms + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.FamilyHomes.Item.Relationships.Rooms.RoomsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/FamilyHomes/Item/Relationships/Rooms/RoomsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/FamilyHomes/Item/Relationships/Rooms/RoomsRequestBuilder.cs new file mode 100644 index 0000000000..0d45a32849 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/FamilyHomes/Item/Relationships/Rooms/RoomsRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.FamilyHomes.Item.Relationships.Rooms +{ + /// + /// Builds and executes requests for operations under \familyHomes\{id}\relationships\rooms + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes/{id}/relationships/rooms{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RoomsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/familyHomes/{id}/relationships/rooms{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related room identities of an individual familyHome's rooms relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoomIdentifierCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related room identities of an individual familyHome's rooms relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.FamilyHomes.Item.Relationships.Rooms.RoomsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.FamilyHomes.Item.Relationships.Rooms.RoomsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related room identities of an individual familyHome's rooms relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RoomsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInBathroomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInBathroomResponse.cs new file mode 100644 index 0000000000..f51562d350 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInBathroomResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInBathroomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// The hasBath property + public bool? HasBath + { + get { return BackingStore?.Get("hasBath"); } + set { BackingStore?.Set("hasBath", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInBathroomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInBathroomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasBath", n => { HasBath = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasBath", HasBath); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInBedroomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInBedroomResponse.cs new file mode 100644 index 0000000000..6c44ab0a6a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInBedroomResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInBedroomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// The bedCount property + public int? BedCount + { + get { return BackingStore?.Get("bedCount"); } + set { BackingStore?.Set("bedCount", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInBedroomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInBedroomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "bedCount", n => { BedCount = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("bedCount", BedCount); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInBuildingResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInBuildingResponse.cs new file mode 100644 index 0000000000..66b88075f7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInBuildingResponse.cs @@ -0,0 +1,66 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInBuildingResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The surfaceInSquareMeters property + public int? SurfaceInSquareMeters + { + get { return BackingStore?.Get("surfaceInSquareMeters"); } + set { BackingStore?.Set("surfaceInSquareMeters", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInBuildingResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInFamilyHomeResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInMansionResponse(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInResidenceResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInBuildingResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "surfaceInSquareMeters", n => { SurfaceInSquareMeters = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("surfaceInSquareMeters", SurfaceInSquareMeters); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInCreateBuildingRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInCreateBuildingRequest.cs new file mode 100644 index 0000000000..f4ff046637 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInCreateBuildingRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateBuildingRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The surfaceInSquareMeters property + public int? SurfaceInSquareMeters + { + get { return BackingStore?.Get("surfaceInSquareMeters"); } + set { BackingStore?.Set("surfaceInSquareMeters", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCreateBuildingRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCreateBuildingRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "surfaceInSquareMeters", n => { SurfaceInSquareMeters = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("surfaceInSquareMeters", SurfaceInSquareMeters); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInCreateFamilyHomeRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInCreateFamilyHomeRequest.cs new file mode 100644 index 0000000000..59f327fe48 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInCreateFamilyHomeRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateFamilyHomeRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCreateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// The floorCount property + public int? FloorCount + { + get { return BackingStore?.Get("floorCount"); } + set { BackingStore?.Set("floorCount", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCreateFamilyHomeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCreateFamilyHomeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "floorCount", n => { FloorCount = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("floorCount", FloorCount); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInCreateMansionRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInCreateMansionRequest.cs new file mode 100644 index 0000000000..df3c20bcb9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInCreateMansionRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateMansionRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCreateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// The ownerName property + public string? OwnerName + { + get { return BackingStore?.Get("ownerName"); } + set { BackingStore?.Set("ownerName", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCreateMansionRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCreateMansionRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "ownerName", n => { OwnerName = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("ownerName", OwnerName); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInCreateRequest.cs new file mode 100644 index 0000000000..9d7f3b41b8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInCreateRequest.cs @@ -0,0 +1,78 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCreateBuildingRequest(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCreateFamilyHomeRequest(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCreateMansionRequest(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCreateResidenceRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInCreateResidenceRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInCreateResidenceRequest.cs new file mode 100644 index 0000000000..e2a33c7932 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInCreateResidenceRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateResidenceRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCreateBuildingRequest, IParsable + #pragma warning restore CS1591 + { + /// The numberOfResidents property + public int? NumberOfResidents + { + get { return BackingStore?.Get("numberOfResidents"); } + set { BackingStore?.Set("numberOfResidents", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCreateResidenceRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCreateResidenceRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "numberOfResidents", n => { NumberOfResidents = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("numberOfResidents", NumberOfResidents); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInCyclePathResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInCyclePathResponse.cs new file mode 100644 index 0000000000..4a42106037 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInCyclePathResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCyclePathResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInRoadResponse, IParsable + #pragma warning restore CS1591 + { + /// The hasLaneForPedestrians property + public bool? HasLaneForPedestrians + { + get { return BackingStore?.Get("hasLaneForPedestrians"); } + set { BackingStore?.Set("hasLaneForPedestrians", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCyclePathResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCyclePathResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasLaneForPedestrians", n => { HasLaneForPedestrians = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasLaneForPedestrians", HasLaneForPedestrians); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInDistrictResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInDistrictResponse.cs new file mode 100644 index 0000000000..38e8c822d7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInDistrictResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInDistrictResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInDistrictResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInDistrictResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInFamilyHomeResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInFamilyHomeResponse.cs new file mode 100644 index 0000000000..71753666e9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInFamilyHomeResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInFamilyHomeResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInResidenceResponse, IParsable + #pragma warning restore CS1591 + { + /// The floorCount property + public int? FloorCount + { + get { return BackingStore?.Get("floorCount"); } + set { BackingStore?.Set("floorCount", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInFamilyHomeResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInFamilyHomeResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "floorCount", n => { FloorCount = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("floorCount", FloorCount); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInKitchenResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInKitchenResponse.cs new file mode 100644 index 0000000000..9cf8215f88 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInKitchenResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInKitchenResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// The hasPantry property + public bool? HasPantry + { + get { return BackingStore?.Get("hasPantry"); } + set { BackingStore?.Set("hasPantry", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInKitchenResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInKitchenResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasPantry", n => { HasPantry = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasPantry", HasPantry); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInLivingRoomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInLivingRoomResponse.cs new file mode 100644 index 0000000000..a98472a4e1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInLivingRoomResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInLivingRoomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// The hasDiningTable property + public bool? HasDiningTable + { + get { return BackingStore?.Get("hasDiningTable"); } + set { BackingStore?.Set("hasDiningTable", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInLivingRoomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInLivingRoomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasDiningTable", n => { HasDiningTable = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasDiningTable", HasDiningTable); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInMansionResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInMansionResponse.cs new file mode 100644 index 0000000000..6a6480ecc6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInMansionResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInMansionResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInResidenceResponse, IParsable + #pragma warning restore CS1591 + { + /// The ownerName property + public string? OwnerName + { + get { return BackingStore?.Get("ownerName"); } + set { BackingStore?.Set("ownerName", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInMansionResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInMansionResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "ownerName", n => { OwnerName = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("ownerName", OwnerName); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInResidenceResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInResidenceResponse.cs new file mode 100644 index 0000000000..2f44b26537 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInResidenceResponse.cs @@ -0,0 +1,65 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInResidenceResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInBuildingResponse, IParsable + #pragma warning restore CS1591 + { + /// The numberOfResidents property + public int? NumberOfResidents + { + get { return BackingStore?.Get("numberOfResidents"); } + set { BackingStore?.Set("numberOfResidents", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInResidenceResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInFamilyHomeResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInMansionResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInResidenceResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "numberOfResidents", n => { NumberOfResidents = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("numberOfResidents", NumberOfResidents); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInResponse.cs new file mode 100644 index 0000000000..f3c19d45ad --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInBathroomResponse(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInBedroomResponse(), + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInBuildingResponse(), + "cyclePaths" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCyclePathResponse(), + "districts" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInDistrictResponse(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInFamilyHomeResponse(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInKitchenResponse(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInLivingRoomResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInMansionResponse(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInResidenceResponse(), + "roads" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInRoadResponse(), + "rooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInRoomResponse(), + "staffMembers" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInStaffMemberResponse(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInToiletResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInRoadResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInRoadResponse.cs new file mode 100644 index 0000000000..5076e5f002 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInRoadResponse.cs @@ -0,0 +1,64 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInRoadResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The lengthInMeters property + public double? LengthInMeters + { + get { return BackingStore?.Get("lengthInMeters"); } + set { BackingStore?.Set("lengthInMeters", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInRoadResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "cyclePaths" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCyclePathResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInRoadResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "lengthInMeters", n => { LengthInMeters = n.GetDoubleValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteDoubleValue("lengthInMeters", LengthInMeters); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInRoomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInRoomResponse.cs new file mode 100644 index 0000000000..618fec1da5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInRoomResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInRoomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The surfaceInSquareMeters property + public int? SurfaceInSquareMeters + { + get { return BackingStore?.Get("surfaceInSquareMeters"); } + set { BackingStore?.Set("surfaceInSquareMeters", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInRoomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInBathroomResponse(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInBedroomResponse(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInKitchenResponse(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInLivingRoomResponse(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInToiletResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInRoomResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "surfaceInSquareMeters", n => { SurfaceInSquareMeters = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("surfaceInSquareMeters", SurfaceInSquareMeters); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInStaffMemberResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInStaffMemberResponse.cs new file mode 100644 index 0000000000..4105e56251 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInStaffMemberResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInStaffMemberResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInStaffMemberResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInStaffMemberResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInToiletResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInToiletResponse.cs new file mode 100644 index 0000000000..2a4ac1e55e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInToiletResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInToiletResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// The hasSink property + public bool? HasSink + { + get { return BackingStore?.Get("hasSink"); } + set { BackingStore?.Set("hasSink", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInToiletResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInToiletResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "hasSink", n => { HasSink = n.GetBoolValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("hasSink", HasSink); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInUpdateBuildingRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInUpdateBuildingRequest.cs new file mode 100644 index 0000000000..36a77baa7e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInUpdateBuildingRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateBuildingRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The surfaceInSquareMeters property + public int? SurfaceInSquareMeters + { + get { return BackingStore?.Get("surfaceInSquareMeters"); } + set { BackingStore?.Set("surfaceInSquareMeters", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInUpdateBuildingRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInUpdateBuildingRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "surfaceInSquareMeters", n => { SurfaceInSquareMeters = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("surfaceInSquareMeters", SurfaceInSquareMeters); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInUpdateFamilyHomeRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInUpdateFamilyHomeRequest.cs new file mode 100644 index 0000000000..14d8a06e14 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInUpdateFamilyHomeRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateFamilyHomeRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInUpdateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// The floorCount property + public int? FloorCount + { + get { return BackingStore?.Get("floorCount"); } + set { BackingStore?.Set("floorCount", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInUpdateFamilyHomeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInUpdateFamilyHomeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "floorCount", n => { FloorCount = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("floorCount", FloorCount); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInUpdateMansionRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInUpdateMansionRequest.cs new file mode 100644 index 0000000000..d7da56cfb5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInUpdateMansionRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateMansionRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInUpdateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// The ownerName property + public string? OwnerName + { + get { return BackingStore?.Get("ownerName"); } + set { BackingStore?.Set("ownerName", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInUpdateMansionRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInUpdateMansionRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "ownerName", n => { OwnerName = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("ownerName", OwnerName); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInUpdateRequest.cs new file mode 100644 index 0000000000..9136076afd --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInUpdateRequest.cs @@ -0,0 +1,78 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInUpdateBuildingRequest(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInUpdateFamilyHomeRequest(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInUpdateMansionRequest(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInUpdateResidenceRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInUpdateResidenceRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInUpdateResidenceRequest.cs new file mode 100644 index 0000000000..7196132595 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/AttributesInUpdateResidenceRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateResidenceRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInUpdateBuildingRequest, IParsable + #pragma warning restore CS1591 + { + /// The numberOfResidents property + public int? NumberOfResidents + { + get { return BackingStore?.Get("numberOfResidents"); } + set { BackingStore?.Set("numberOfResidents", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInUpdateResidenceRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInUpdateResidenceRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "numberOfResidents", n => { NumberOfResidents = n.GetIntValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteIntValue("numberOfResidents", NumberOfResidents); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/BathroomIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/BathroomIdentifierInRequest.cs new file mode 100644 index 0000000000..c8667f2d5a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/BathroomIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BathroomIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoomIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.BathroomIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.BathroomIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/BathroomIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/BathroomIdentifierInResponse.cs new file mode 100644 index 0000000000..91265e0f2e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/BathroomIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BathroomIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoomIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.BathroomIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.BathroomIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/BedroomIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/BedroomIdentifierInRequest.cs new file mode 100644 index 0000000000..15ecf781e2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/BedroomIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BedroomIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoomIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.BedroomIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.BedroomIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/BedroomIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/BedroomIdentifierInResponse.cs new file mode 100644 index 0000000000..35b78a160d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/BedroomIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BedroomIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoomIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.BedroomIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.BedroomIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/BuildingIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/BuildingIdentifierInResponse.cs new file mode 100644 index 0000000000..2f8239c39d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/BuildingIdentifierInResponse.cs @@ -0,0 +1,95 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class BuildingIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.BuildingResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public BuildingIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.BuildingIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.FamilyHomeIdentifierInResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.MansionIdentifierInResponse(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResidenceIdentifierInResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.BuildingIdentifierInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/BuildingResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/BuildingResourceType.cs new file mode 100644 index 0000000000..2222502413 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/BuildingResourceType.cs @@ -0,0 +1,26 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum BuildingResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "familyHomes")] + #pragma warning disable CS1591 + FamilyHomes, + #pragma warning restore CS1591 + [EnumMember(Value = "mansions")] + #pragma warning disable CS1591 + Mansions, + #pragma warning restore CS1591 + [EnumMember(Value = "residences")] + #pragma warning disable CS1591 + Residences, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/CreateBuildingRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/CreateBuildingRequestDocument.cs new file mode 100644 index 0000000000..873b8e6ca2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/CreateBuildingRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateBuildingRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInCreateBuildingRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateBuildingRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.CreateBuildingRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.CreateBuildingRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInCreateBuildingRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/CyclePathIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/CyclePathIdentifierInResponse.cs new file mode 100644 index 0000000000..07cfbbc48e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/CyclePathIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CyclePathIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoadIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.CyclePathIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.CyclePathIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInBathroomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInBathroomResponse.cs new file mode 100644 index 0000000000..0899b315b6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInBathroomResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInBathroomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInBathroomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInBathroomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInBedroomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInBedroomResponse.cs new file mode 100644 index 0000000000..62b79767e7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInBedroomResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInBedroomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInBedroomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInBedroomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInBuildingResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInBuildingResponse.cs new file mode 100644 index 0000000000..d14abd360a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInBuildingResponse.cs @@ -0,0 +1,93 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInBuildingResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInBuildingResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInBuildingResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInBuildingResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInFamilyHomeResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInMansionResponse(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInResidenceResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInBuildingResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInBuildingResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInBuildingResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInCreateBuildingRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInCreateBuildingRequest.cs new file mode 100644 index 0000000000..30450c2557 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInCreateBuildingRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateBuildingRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCreateBuildingRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCreateBuildingRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInCreateBuildingRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInCreateBuildingRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInCreateBuildingRequest.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCreateBuildingRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInCreateFamilyHomeRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInCreateFamilyHomeRequest.cs new file mode 100644 index 0000000000..41e0cc12dd --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInCreateFamilyHomeRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateFamilyHomeRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInCreateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInCreateFamilyHomeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInCreateFamilyHomeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInCreateMansionRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInCreateMansionRequest.cs new file mode 100644 index 0000000000..2b17ea5c87 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInCreateMansionRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateMansionRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInCreateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInCreateMansionRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInCreateMansionRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInCreateResidenceRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInCreateResidenceRequest.cs new file mode 100644 index 0000000000..736bbef4db --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInCreateResidenceRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateResidenceRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInCreateBuildingRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInCreateResidenceRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInCreateResidenceRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInCyclePathResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInCyclePathResponse.cs new file mode 100644 index 0000000000..55c88a9abb --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInCyclePathResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCyclePathResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInRoadResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInCyclePathResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInCyclePathResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInDistrictResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInDistrictResponse.cs new file mode 100644 index 0000000000..dd086726b5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInDistrictResponse.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInDistrictResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInDistrictResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public Guid? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInDistrictResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInDistrictResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInDistrictResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInDistrictResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetGuidValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInDistrictResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteGuidValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInFamilyHomeResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInFamilyHomeResponse.cs new file mode 100644 index 0000000000..07aeee39b0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInFamilyHomeResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInFamilyHomeResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInResidenceResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInFamilyHomeResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInFamilyHomeResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInKitchenResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInKitchenResponse.cs new file mode 100644 index 0000000000..9f8c881ce1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInKitchenResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInKitchenResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInKitchenResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInKitchenResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInLivingRoomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInLivingRoomResponse.cs new file mode 100644 index 0000000000..74738018a5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInLivingRoomResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInLivingRoomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInLivingRoomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInLivingRoomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInMansionResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInMansionResponse.cs new file mode 100644 index 0000000000..5943bcefeb --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInMansionResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInMansionResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInResidenceResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInMansionResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInMansionResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInResidenceResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInResidenceResponse.cs new file mode 100644 index 0000000000..09ecacb0a0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInResidenceResponse.cs @@ -0,0 +1,56 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInResidenceResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInBuildingResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInResidenceResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInFamilyHomeResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInMansionResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInResidenceResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInRoadResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInRoadResponse.cs new file mode 100644 index 0000000000..75a85a06c4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInRoadResponse.cs @@ -0,0 +1,91 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInRoadResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInRoadResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInRoadResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInRoadResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "cyclePaths" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInCyclePathResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInRoadResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInRoadResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInRoadResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInRoomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInRoomResponse.cs new file mode 100644 index 0000000000..f9bba2e9af --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInRoomResponse.cs @@ -0,0 +1,95 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInRoomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInRoomResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInRoomResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInRoomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInBathroomResponse(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInBedroomResponse(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInKitchenResponse(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInLivingRoomResponse(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInToiletResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInRoomResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInRoomResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInRoomResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInStaffMemberResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInStaffMemberResponse.cs new file mode 100644 index 0000000000..68850b163c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInStaffMemberResponse.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInStaffMemberResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInStaffMemberResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInStaffMemberResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInStaffMemberResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInStaffMemberResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInToiletResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInToiletResponse.cs new file mode 100644 index 0000000000..ac2e5be1b3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInToiletResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInToiletResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInToiletResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInToiletResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInUpdateBuildingRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInUpdateBuildingRequest.cs new file mode 100644 index 0000000000..4ca06b894b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInUpdateBuildingRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateBuildingRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInUpdateBuildingRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInUpdateBuildingRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInUpdateBuildingRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInUpdateBuildingRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.AttributesInUpdateBuildingRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInUpdateBuildingRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInUpdateFamilyHomeRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInUpdateFamilyHomeRequest.cs new file mode 100644 index 0000000000..5d84c23f2b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInUpdateFamilyHomeRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateFamilyHomeRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInUpdateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInUpdateFamilyHomeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInUpdateFamilyHomeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInUpdateMansionRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInUpdateMansionRequest.cs new file mode 100644 index 0000000000..66dcfd88ff --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInUpdateMansionRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateMansionRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInUpdateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInUpdateMansionRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInUpdateMansionRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInUpdateResidenceRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInUpdateResidenceRequest.cs new file mode 100644 index 0000000000..4137f1e4b2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DataInUpdateResidenceRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateResidenceRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInUpdateBuildingRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInUpdateResidenceRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInUpdateResidenceRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DistrictCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DistrictCollectionResponseDocument.cs new file mode 100644 index 0000000000..d97ffc5736 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/DistrictCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DistrictCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public DistrictCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DistrictCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DistrictCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInDistrictResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ErrorLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ErrorLinks.cs new file mode 100644 index 0000000000..673ff6cc69 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ErrorLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// The about property + public string? About + { + get { return BackingStore?.Get("about"); } + set { BackingStore?.Set("about", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The type property + public string? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "about", n => { About = n.GetStringValue(); } }, + { "type", n => { Type = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("about", About); + writer.WriteStringValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ErrorObject.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ErrorObject.cs new file mode 100644 index 0000000000..9303d07110 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ErrorObject.cs @@ -0,0 +1,133 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorObject : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The code property + public string? Code + { + get { return BackingStore?.Get("code"); } + set { BackingStore?.Set("code", value); } + } + + /// The detail property + public string? Detail + { + get { return BackingStore?.Get("detail"); } + set { BackingStore?.Set("detail", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The source property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorSource? Source + { + get { return BackingStore?.Get("source"); } + set { BackingStore?.Set("source", value); } + } + + /// The status property + public string? Status + { + get { return BackingStore?.Get("status"); } + set { BackingStore?.Set("status", value); } + } + + /// The title property + public string? Title + { + get { return BackingStore?.Get("title"); } + set { BackingStore?.Set("title", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorObject() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorObject CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorObject(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "code", n => { Code = n.GetStringValue(); } }, + { "detail", n => { Detail = n.GetStringValue(); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "source", n => { Source = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorSource.CreateFromDiscriminatorValue); } }, + { "status", n => { Status = n.GetStringValue(); } }, + { "title", n => { Title = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("code", Code); + writer.WriteStringValue("detail", Detail); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + writer.WriteObjectValue("source", Source); + writer.WriteStringValue("status", Status); + writer.WriteStringValue("title", Title); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ErrorResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ErrorResponseDocument.cs new file mode 100644 index 0000000000..4376a86884 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ErrorResponseDocument.cs @@ -0,0 +1,92 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorResponseDocument : ApiException, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The errors property + public List? Errors + { + get { return BackingStore?.Get?>("errors"); } + set { BackingStore?.Set("errors", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The primary error message. + public override string Message { get => base.Message; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "errors", n => { Errors = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorObject.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("errors", Errors); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ErrorSource.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ErrorSource.cs new file mode 100644 index 0000000000..23f6c86d5a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ErrorSource.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorSource : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The header property + public string? Header + { + get { return BackingStore?.Get("header"); } + set { BackingStore?.Set("header", value); } + } + + /// The parameter property + public string? Parameter + { + get { return BackingStore?.Get("parameter"); } + set { BackingStore?.Set("parameter", value); } + } + + /// The pointer property + public string? Pointer + { + get { return BackingStore?.Get("pointer"); } + set { BackingStore?.Set("pointer", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorSource() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorSource CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorSource(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "header", n => { Header = n.GetStringValue(); } }, + { "parameter", n => { Parameter = n.GetStringValue(); } }, + { "pointer", n => { Pointer = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("header", Header); + writer.WriteStringValue("parameter", Parameter); + writer.WriteStringValue("pointer", Pointer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ErrorTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ErrorTopLevelLinks.cs new file mode 100644 index 0000000000..d3e59f8189 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ErrorTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ErrorTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/FamilyHomeIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/FamilyHomeIdentifierInResponse.cs new file mode 100644 index 0000000000..351eb51dd1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/FamilyHomeIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class FamilyHomeIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResidenceIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.FamilyHomeIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.FamilyHomeIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/IdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/IdentifierInRequest.cs new file mode 100644 index 0000000000..1d781d6591 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/IdentifierInRequest.cs @@ -0,0 +1,90 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class IdentifierInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public IdentifierInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.IdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.BathroomIdentifierInRequest(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.BedroomIdentifierInRequest(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.KitchenIdentifierInRequest(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.LivingRoomIdentifierInRequest(), + "rooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoomIdentifierInRequest(), + "staffMembers" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.StaffMemberIdentifierInRequest(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToiletIdentifierInRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.IdentifierInRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/KitchenIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/KitchenIdentifierInRequest.cs new file mode 100644 index 0000000000..2deed42b37 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/KitchenIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class KitchenIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoomIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.KitchenIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.KitchenIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/KitchenIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/KitchenIdentifierInResponse.cs new file mode 100644 index 0000000000..2b4bdcf012 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/KitchenIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class KitchenIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoomIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.KitchenIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.KitchenIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/LivingRoomIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/LivingRoomIdentifierInRequest.cs new file mode 100644 index 0000000000..b49157ed7f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/LivingRoomIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class LivingRoomIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoomIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.LivingRoomIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.LivingRoomIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/LivingRoomIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/LivingRoomIdentifierInResponse.cs new file mode 100644 index 0000000000..eed8947a34 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/LivingRoomIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class LivingRoomIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoomIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.LivingRoomIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.LivingRoomIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/MansionIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/MansionIdentifierInResponse.cs new file mode 100644 index 0000000000..83f7656f32 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/MansionIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class MansionIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResidenceIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.MansionIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.MansionIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/Meta.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/Meta.cs new file mode 100644 index 0000000000..89d5f431a0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/Meta.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class Meta : IAdditionalDataHolder, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + public IDictionary AdditionalData + { + get { return BackingStore.Get>("AdditionalData") ?? new Dictionary(); } + set { BackingStore.Set("AdditionalData", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// + /// Instantiates a new and sets the default values. + /// + public Meta() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + AdditionalData = new Dictionary(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteAdditionalData(AdditionalData); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/PrimaryBuildingResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/PrimaryBuildingResponseDocument.cs new file mode 100644 index 0000000000..38250f348d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/PrimaryBuildingResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryBuildingResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInBuildingResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryBuildingResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.PrimaryBuildingResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.PrimaryBuildingResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInBuildingResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/PrimaryCyclePathResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/PrimaryCyclePathResponseDocument.cs new file mode 100644 index 0000000000..b206ebc91c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/PrimaryCyclePathResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryCyclePathResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInCyclePathResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryCyclePathResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.PrimaryCyclePathResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.PrimaryCyclePathResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInCyclePathResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipLinks.cs new file mode 100644 index 0000000000..41478b1ec3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInBathroomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInBathroomResponse.cs new file mode 100644 index 0000000000..fa353a6c65 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInBathroomResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInBathroomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInBathroomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInBathroomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInBedroomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInBedroomResponse.cs new file mode 100644 index 0000000000..77d81a7b64 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInBedroomResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInBedroomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInBedroomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInBedroomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInBuildingResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInBuildingResponse.cs new file mode 100644 index 0000000000..c18d2bce59 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInBuildingResponse.cs @@ -0,0 +1,57 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInBuildingResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInBuildingResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInFamilyHomeResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInMansionResponse(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInResidenceResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInBuildingResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInCreateBuildingRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInCreateBuildingRequest.cs new file mode 100644 index 0000000000..62c52b5ec4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInCreateBuildingRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateBuildingRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCreateBuildingRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCreateBuildingRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInCreateFamilyHomeRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInCreateFamilyHomeRequest.cs new file mode 100644 index 0000000000..25fcd4de43 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInCreateFamilyHomeRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateFamilyHomeRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCreateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCreateFamilyHomeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCreateFamilyHomeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInCreateMansionRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInCreateMansionRequest.cs new file mode 100644 index 0000000000..5d7bfd7a9a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInCreateMansionRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateMansionRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCreateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// The staff property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyStaffMemberInRequest? Staff + { + get { return BackingStore?.Get("staff"); } + set { BackingStore?.Set("staff", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCreateMansionRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCreateMansionRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "staff", n => { Staff = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyStaffMemberInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("staff", Staff); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInCreateRequest.cs new file mode 100644 index 0000000000..419975712e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInCreateRequest.cs @@ -0,0 +1,78 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCreateBuildingRequest(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCreateFamilyHomeRequest(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCreateMansionRequest(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCreateResidenceRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInCreateResidenceRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInCreateResidenceRequest.cs new file mode 100644 index 0000000000..bbb02cba5e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInCreateResidenceRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateResidenceRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCreateBuildingRequest, IParsable + #pragma warning restore CS1591 + { + /// The rooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyRoomInRequest? Rooms + { + get { return BackingStore?.Get("rooms"); } + set { BackingStore?.Set("rooms", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCreateResidenceRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCreateResidenceRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "rooms", n => { Rooms = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyRoomInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("rooms", Rooms); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInCyclePathResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInCyclePathResponse.cs new file mode 100644 index 0000000000..bd4d9ef5de --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInCyclePathResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCyclePathResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInRoadResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCyclePathResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCyclePathResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInDistrictResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInDistrictResponse.cs new file mode 100644 index 0000000000..80c9044b3d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInDistrictResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInDistrictResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// The buildings property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyBuildingInResponse? Buildings + { + get { return BackingStore?.Get("buildings"); } + set { BackingStore?.Set("buildings", value); } + } + + /// The roads property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyRoadInResponse? Roads + { + get { return BackingStore?.Get("roads"); } + set { BackingStore?.Set("roads", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInDistrictResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInDistrictResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "buildings", n => { Buildings = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyBuildingInResponse.CreateFromDiscriminatorValue); } }, + { "roads", n => { Roads = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyRoadInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("buildings", Buildings); + writer.WriteObjectValue("roads", Roads); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInFamilyHomeResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInFamilyHomeResponse.cs new file mode 100644 index 0000000000..dac880d49a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInFamilyHomeResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInFamilyHomeResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInResidenceResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInFamilyHomeResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInFamilyHomeResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInKitchenResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInKitchenResponse.cs new file mode 100644 index 0000000000..8e90ff1076 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInKitchenResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInKitchenResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInKitchenResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInKitchenResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInLivingRoomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInLivingRoomResponse.cs new file mode 100644 index 0000000000..e32e7c4626 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInLivingRoomResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInLivingRoomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInLivingRoomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInLivingRoomResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInMansionResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInMansionResponse.cs new file mode 100644 index 0000000000..f79ff1330e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInMansionResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInMansionResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInResidenceResponse, IParsable + #pragma warning restore CS1591 + { + /// The staff property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyStaffMemberInResponse? Staff + { + get { return BackingStore?.Get("staff"); } + set { BackingStore?.Set("staff", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInMansionResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInMansionResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "staff", n => { Staff = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyStaffMemberInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("staff", Staff); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInResidenceResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInResidenceResponse.cs new file mode 100644 index 0000000000..27fb9db71b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInResidenceResponse.cs @@ -0,0 +1,65 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInResidenceResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInBuildingResponse, IParsable + #pragma warning restore CS1591 + { + /// The rooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyRoomInResponse? Rooms + { + get { return BackingStore?.Get("rooms"); } + set { BackingStore?.Set("rooms", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInResidenceResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInFamilyHomeResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInMansionResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInResidenceResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "rooms", n => { Rooms = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyRoomInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("rooms", Rooms); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInResponse.cs new file mode 100644 index 0000000000..0be66e31ad --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInResponse.cs @@ -0,0 +1,87 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInBathroomResponse(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInBedroomResponse(), + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInBuildingResponse(), + "cyclePaths" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCyclePathResponse(), + "districts" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInDistrictResponse(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInFamilyHomeResponse(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInKitchenResponse(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInLivingRoomResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInMansionResponse(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInResidenceResponse(), + "roads" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInRoadResponse(), + "rooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInRoomResponse(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInToiletResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInRoadResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInRoadResponse.cs new file mode 100644 index 0000000000..af23055a11 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInRoadResponse.cs @@ -0,0 +1,55 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInRoadResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInRoadResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "cyclePaths" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInCyclePathResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInRoadResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInRoomResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInRoomResponse.cs new file mode 100644 index 0000000000..6a5d51c9c0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInRoomResponse.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInRoomResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// The residence property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToOneResidenceInResponse? Residence + { + get { return BackingStore?.Get("residence"); } + set { BackingStore?.Set("residence", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInRoomResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInBathroomResponse(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInBedroomResponse(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInKitchenResponse(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInLivingRoomResponse(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInToiletResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInRoomResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "residence", n => { Residence = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToOneResidenceInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("residence", Residence); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInToiletResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInToiletResponse.cs new file mode 100644 index 0000000000..b8b225006c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInToiletResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInToiletResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInRoomResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInToiletResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInToiletResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInUpdateBuildingRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInUpdateBuildingRequest.cs new file mode 100644 index 0000000000..655169e932 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInUpdateBuildingRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateBuildingRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInUpdateBuildingRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInUpdateBuildingRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInUpdateFamilyHomeRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInUpdateFamilyHomeRequest.cs new file mode 100644 index 0000000000..65e1aeb225 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInUpdateFamilyHomeRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateFamilyHomeRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInUpdateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInUpdateFamilyHomeRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInUpdateFamilyHomeRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInUpdateMansionRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInUpdateMansionRequest.cs new file mode 100644 index 0000000000..70e3b955c8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInUpdateMansionRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateMansionRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInUpdateResidenceRequest, IParsable + #pragma warning restore CS1591 + { + /// The staff property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyStaffMemberInRequest? Staff + { + get { return BackingStore?.Get("staff"); } + set { BackingStore?.Set("staff", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInUpdateMansionRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInUpdateMansionRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "staff", n => { Staff = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyStaffMemberInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("staff", Staff); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInUpdateRequest.cs new file mode 100644 index 0000000000..5cd83e1238 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInUpdateRequest.cs @@ -0,0 +1,78 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInUpdateBuildingRequest(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInUpdateFamilyHomeRequest(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInUpdateMansionRequest(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInUpdateResidenceRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInUpdateResidenceRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInUpdateResidenceRequest.cs new file mode 100644 index 0000000000..b45ac2e7c7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RelationshipsInUpdateResidenceRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateResidenceRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInUpdateBuildingRequest, IParsable + #pragma warning restore CS1591 + { + /// The rooms property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyRoomInRequest? Rooms + { + get { return BackingStore?.Get("rooms"); } + set { BackingStore?.Set("rooms", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInUpdateResidenceRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipsInUpdateResidenceRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "rooms", n => { Rooms = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyRoomInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("rooms", Rooms); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResidenceIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResidenceIdentifierInResponse.cs new file mode 100644 index 0000000000..b7440b239b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResidenceIdentifierInResponse.cs @@ -0,0 +1,56 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResidenceIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.BuildingIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResidenceIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.FamilyHomeIdentifierInResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.MansionIdentifierInResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResidenceIdentifierInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceCollectionTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceCollectionTopLevelLinks.cs new file mode 100644 index 0000000000..7dc32d06b6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceCollectionTopLevelLinks.cs @@ -0,0 +1,115 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceCollectionTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The first property + public string? First + { + get { return BackingStore?.Get("first"); } + set { BackingStore?.Set("first", value); } + } + + /// The last property + public string? Last + { + get { return BackingStore?.Get("last"); } + set { BackingStore?.Set("last", value); } + } + + /// The next property + public string? Next + { + get { return BackingStore?.Get("next"); } + set { BackingStore?.Set("next", value); } + } + + /// The prev property + public string? Prev + { + get { return BackingStore?.Get("prev"); } + set { BackingStore?.Set("prev", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceCollectionTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceCollectionTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceCollectionTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "first", n => { First = n.GetStringValue(); } }, + { "last", n => { Last = n.GetStringValue(); } }, + { "next", n => { Next = n.GetStringValue(); } }, + { "prev", n => { Prev = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("first", First); + writer.WriteStringValue("last", Last); + writer.WriteStringValue("next", Next); + writer.WriteStringValue("prev", Prev); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs new file mode 100644 index 0000000000..85b409632a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs @@ -0,0 +1,124 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceIdentifierCollectionTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The first property + public string? First + { + get { return BackingStore?.Get("first"); } + set { BackingStore?.Set("first", value); } + } + + /// The last property + public string? Last + { + get { return BackingStore?.Get("last"); } + set { BackingStore?.Set("last", value); } + } + + /// The next property + public string? Next + { + get { return BackingStore?.Get("next"); } + set { BackingStore?.Set("next", value); } + } + + /// The prev property + public string? Prev + { + get { return BackingStore?.Get("prev"); } + set { BackingStore?.Set("prev", value); } + } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceIdentifierCollectionTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "first", n => { First = n.GetStringValue(); } }, + { "last", n => { Last = n.GetStringValue(); } }, + { "next", n => { Next = n.GetStringValue(); } }, + { "prev", n => { Prev = n.GetStringValue(); } }, + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("first", First); + writer.WriteStringValue("last", Last); + writer.WriteStringValue("next", Next); + writer.WriteStringValue("prev", Prev); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceInCreateRequest.cs new file mode 100644 index 0000000000..2c679847d0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceInCreateRequest.cs @@ -0,0 +1,87 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInCreateBuildingRequest(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInCreateFamilyHomeRequest(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInCreateMansionRequest(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInCreateResidenceRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceInResponse.cs new file mode 100644 index 0000000000..7706ae85b7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceInResponse.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInBathroomResponse(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInBedroomResponse(), + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInBuildingResponse(), + "cyclePaths" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInCyclePathResponse(), + "districts" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInDistrictResponse(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInFamilyHomeResponse(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInKitchenResponse(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInLivingRoomResponse(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInMansionResponse(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInResidenceResponse(), + "roads" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInRoadResponse(), + "rooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInRoomResponse(), + "staffMembers" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInStaffMemberResponse(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInToiletResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceInUpdateRequest.cs new file mode 100644 index 0000000000..6a079b9a5d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceInUpdateRequest.cs @@ -0,0 +1,87 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "buildings" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInUpdateBuildingRequest(), + "familyHomes" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInUpdateFamilyHomeRequest(), + "mansions" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInUpdateMansionRequest(), + "residences" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInUpdateResidenceRequest(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceLinks.cs new file mode 100644 index 0000000000..820dd6691d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceLinks.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceTopLevelLinks.cs new file mode 100644 index 0000000000..5619412cd0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceType.cs new file mode 100644 index 0000000000..d5b1a5cc92 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ResourceType.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum ResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "bathrooms")] + #pragma warning disable CS1591 + Bathrooms, + #pragma warning restore CS1591 + [EnumMember(Value = "bedrooms")] + #pragma warning disable CS1591 + Bedrooms, + #pragma warning restore CS1591 + [EnumMember(Value = "buildings")] + #pragma warning disable CS1591 + Buildings, + #pragma warning restore CS1591 + [EnumMember(Value = "cyclePaths")] + #pragma warning disable CS1591 + CyclePaths, + #pragma warning restore CS1591 + [EnumMember(Value = "districts")] + #pragma warning disable CS1591 + Districts, + #pragma warning restore CS1591 + [EnumMember(Value = "familyHomes")] + #pragma warning disable CS1591 + FamilyHomes, + #pragma warning restore CS1591 + [EnumMember(Value = "kitchens")] + #pragma warning disable CS1591 + Kitchens, + #pragma warning restore CS1591 + [EnumMember(Value = "livingRooms")] + #pragma warning disable CS1591 + LivingRooms, + #pragma warning restore CS1591 + [EnumMember(Value = "mansions")] + #pragma warning disable CS1591 + Mansions, + #pragma warning restore CS1591 + [EnumMember(Value = "residences")] + #pragma warning disable CS1591 + Residences, + #pragma warning restore CS1591 + [EnumMember(Value = "roads")] + #pragma warning disable CS1591 + Roads, + #pragma warning restore CS1591 + [EnumMember(Value = "rooms")] + #pragma warning disable CS1591 + Rooms, + #pragma warning restore CS1591 + [EnumMember(Value = "staffMembers")] + #pragma warning disable CS1591 + StaffMembers, + #pragma warning restore CS1591 + [EnumMember(Value = "toilets")] + #pragma warning disable CS1591 + Toilets, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RoadIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RoadIdentifierInResponse.cs new file mode 100644 index 0000000000..2be26c8741 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RoadIdentifierInResponse.cs @@ -0,0 +1,93 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RoadIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoadResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RoadIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoadIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "cyclePaths" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.CyclePathIdentifierInResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoadIdentifierInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RoadResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RoadResourceType.cs new file mode 100644 index 0000000000..1c560a02a4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RoadResourceType.cs @@ -0,0 +1,22 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum RoadResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "cyclePaths")] + #pragma warning disable CS1591 + CyclePaths, + #pragma warning restore CS1591 + [EnumMember(Value = "roads")] + #pragma warning disable CS1591 + Roads, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RoomIdentifierCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RoomIdentifierCollectionResponseDocument.cs new file mode 100644 index 0000000000..01a4ccf479 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RoomIdentifierCollectionResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RoomIdentifierCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RoomIdentifierCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoomIdentifierCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoomIdentifierCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoomIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RoomIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RoomIdentifierInRequest.cs new file mode 100644 index 0000000000..aaddb4e5bb --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RoomIdentifierInRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RoomIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoomIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoomIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RoomIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RoomIdentifierInResponse.cs new file mode 100644 index 0000000000..193c047e5d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RoomIdentifierInResponse.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RoomIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoomResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RoomIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoomIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "bathrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.BathroomIdentifierInResponse(), + "bedrooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.BedroomIdentifierInResponse(), + "kitchens" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.KitchenIdentifierInResponse(), + "livingRooms" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.LivingRoomIdentifierInResponse(), + "toilets" => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToiletIdentifierInResponse(), + _ => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoomIdentifierInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RoomResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RoomResourceType.cs new file mode 100644 index 0000000000..f576271515 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/RoomResourceType.cs @@ -0,0 +1,34 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum RoomResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "bathrooms")] + #pragma warning disable CS1591 + Bathrooms, + #pragma warning restore CS1591 + [EnumMember(Value = "bedrooms")] + #pragma warning disable CS1591 + Bedrooms, + #pragma warning restore CS1591 + [EnumMember(Value = "kitchens")] + #pragma warning disable CS1591 + Kitchens, + #pragma warning restore CS1591 + [EnumMember(Value = "livingRooms")] + #pragma warning disable CS1591 + LivingRooms, + #pragma warning restore CS1591 + [EnumMember(Value = "toilets")] + #pragma warning disable CS1591 + Toilets, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/StaffMemberIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/StaffMemberIdentifierInRequest.cs new file mode 100644 index 0000000000..be1f9d92ca --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/StaffMemberIdentifierInRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class StaffMemberIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.StaffMemberIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.StaffMemberIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/StaffMemberIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/StaffMemberIdentifierInResponse.cs new file mode 100644 index 0000000000..da77c1b8f2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/StaffMemberIdentifierInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class StaffMemberIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.StaffMemberResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public StaffMemberIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.StaffMemberIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.StaffMemberIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/StaffMemberResourceType.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/StaffMemberResourceType.cs new file mode 100644 index 0000000000..204f6b3966 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/StaffMemberResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum StaffMemberResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "staffMembers")] + #pragma warning disable CS1591 + StaffMembers, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToManyBuildingInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToManyBuildingInResponse.cs new file mode 100644 index 0000000000..0c8e337faa --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToManyBuildingInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyBuildingInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyBuildingInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyBuildingInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyBuildingInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.BuildingIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToManyRoadInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToManyRoadInResponse.cs new file mode 100644 index 0000000000..12eab9d58b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToManyRoadInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyRoadInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyRoadInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyRoadInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyRoadInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoadIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToManyRoomInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToManyRoomInRequest.cs new file mode 100644 index 0000000000..5775926ba8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToManyRoomInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyRoomInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyRoomInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyRoomInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyRoomInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoomIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToManyRoomInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToManyRoomInResponse.cs new file mode 100644 index 0000000000..0036f10528 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToManyRoomInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyRoomInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyRoomInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyRoomInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyRoomInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoomIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToManyStaffMemberInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToManyStaffMemberInRequest.cs new file mode 100644 index 0000000000..f931abee1e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToManyStaffMemberInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyStaffMemberInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyStaffMemberInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyStaffMemberInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyStaffMemberInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.StaffMemberIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToManyStaffMemberInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToManyStaffMemberInResponse.cs new file mode 100644 index 0000000000..86614046f1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToManyStaffMemberInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyStaffMemberInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyStaffMemberInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyStaffMemberInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToManyStaffMemberInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.StaffMemberIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToOneResidenceInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToOneResidenceInResponse.cs new file mode 100644 index 0000000000..8a6886cbc2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToOneResidenceInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToOneResidenceInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResidenceIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToOneResidenceInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToOneResidenceInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToOneResidenceInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ResidenceIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToiletIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToiletIdentifierInRequest.cs new file mode 100644 index 0000000000..9571533797 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToiletIdentifierInRequest.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToiletIdentifierInRequest : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoomIdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToiletIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToiletIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToiletIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToiletIdentifierInResponse.cs new file mode 100644 index 0000000000..d2ce05f099 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/ToiletIdentifierInResponse.cs @@ -0,0 +1,50 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToiletIdentifierInResponse : global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.RoomIdentifierInResponse, IParsable + #pragma warning restore CS1591 + { + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToiletIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.ToiletIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/UpdateBuildingRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/UpdateBuildingRequestDocument.cs new file mode 100644 index 0000000000..f22b72fce0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/Models/UpdateBuildingRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateBuildingRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInUpdateBuildingRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateBuildingRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.UpdateBuildingRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.UpdateBuildingRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.DataInUpdateBuildingRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/SubsetOfVariousInheritanceClient.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/SubsetOfVariousInheritanceClient.cs new file mode 100644 index 0000000000..d70ef584dd --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/SubsetOfVariousInheritanceClient.cs @@ -0,0 +1,75 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using Microsoft.Kiota.Serialization.Form; +using Microsoft.Kiota.Serialization.Json; +using Microsoft.Kiota.Serialization.Multipart; +using Microsoft.Kiota.Serialization.Text; +using OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Buildings; +using OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.CyclePaths; +using OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Districts; +using OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.FamilyHomes; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode +{ + /// + /// The main entry point of the SDK, exposes the configuration and the fluent API. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class SubsetOfVariousInheritanceClient : BaseRequestBuilder + { + /// The buildings property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Buildings.BuildingsRequestBuilder Buildings + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Buildings.BuildingsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The cyclePaths property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.CyclePaths.CyclePathsRequestBuilder CyclePaths + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.CyclePaths.CyclePathsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The districts property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Districts.DistrictsRequestBuilder Districts + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Districts.DistrictsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The familyHomes property + public global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.FamilyHomes.FamilyHomesRequestBuilder FamilyHomes + { + get => new global::OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.FamilyHomes.FamilyHomesRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The backing store to use for the models. + /// The request adapter to use to execute the requests. + public SubsetOfVariousInheritanceClient(IRequestAdapter requestAdapter, IBackingStoreFactory backingStore = default) : base(requestAdapter, "{+baseurl}", new Dictionary()) + { + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + if (string.IsNullOrEmpty(RequestAdapter.BaseUrl)) + { + RequestAdapter.BaseUrl = "http://localhost"; + } + PathParameters.TryAdd("baseurl", RequestAdapter.BaseUrl); + RequestAdapter.EnableBackingStore(backingStore); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/IncludeTests.cs b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/IncludeTests.cs new file mode 100644 index 0000000000..7e40d74c18 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/IncludeTests.cs @@ -0,0 +1,151 @@ +using FluentAssertions; +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Middleware; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode; +using OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.ResourceInheritance; +using OpenApiTests.ResourceInheritance.Models; +using OpenApiTests.ResourceInheritance.SubsetOfVarious; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious; + +public sealed class IncludeTests + : IClassFixture, ResourceInheritanceDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, ResourceInheritanceDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly ResourceInheritanceFakers _fakers = new(); + + public IncludeTests(IntegrationTestContext, ResourceInheritanceDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseInheritanceControllers(false); + + testContext.ConfigureServices(services => + { + services.AddSingleton(); + services.AddSingleton(); + }); + } + + [Fact] + public async Task Can_include_in_primary_resources() + { + // Arrange + District district = _fakers.District.GenerateOne(); + + FamilyHome familyHome = _fakers.FamilyHome.GenerateOne(); + familyHome.Rooms.Add(_fakers.LivingRoom.GenerateOne()); + familyHome.Rooms.Add(_fakers.Bedroom.GenerateOne()); + district.Buildings.Add(familyHome); + + Mansion mansion = _fakers.Mansion.GenerateOne(); + mansion.Rooms.Add(_fakers.Kitchen.GenerateOne()); + mansion.Rooms.Add(_fakers.Bathroom.GenerateOne()); + mansion.Rooms.Add(_fakers.Toilet.GenerateOne()); + district.Buildings.Add(mansion); + + Residence residence = _fakers.Residence.GenerateOne(); + residence.Rooms.Add(_fakers.Bedroom.GenerateOne()); + district.Buildings.Add(residence); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Districts.Add(district); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new SubsetOfVariousInheritanceClient(requestAdapter); + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["include"] = "buildings.rooms" + }); + + // Act + DistrictCollectionResponseDocument? response = await apiClient.Districts.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(1); + response.Data.ElementAt(0).Id.Should().Be(district.StringId); + + response.Included.Should().HaveCount(9); + + string familyHomeLivingRoomId = familyHome.Rooms.OfType().Single().StringId!; + string familyRoomBedroomId = familyHome.Rooms.OfType().Single().StringId!; + string mansionKitchenId = mansion.Rooms.OfType().Single().StringId!; + string mansionBathroomId = mansion.Rooms.OfType().Single().StringId!; + string mansionToiletId = mansion.Rooms.OfType().Single().StringId!; + string residenceBedroomId = residence.Rooms.OfType().Single().StringId!; + + response.Included.OfType().Should().ContainSingle(include => include.Id == familyHome.StringId).Subject.With(include => + { + AttributesInFamilyHomeResponse attributes = include.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(familyHome.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(familyHome.NumberOfResidents); + attributes.FloorCount.Should().Be(familyHome.FloorCount); + + RelationshipsInFamilyHomeResponse relationships = include.Relationships.Should().BeOfType().Subject; + + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().HaveCount(2); + relationships.Rooms.Data.OfType().Should().ContainSingle(data => data.Id == familyHomeLivingRoomId); + relationships.Rooms.Data.OfType().Should().ContainSingle(data => data.Id == familyRoomBedroomId); + }); + + response.Included.OfType().Should().ContainSingle(include => include.Id == mansion.StringId).Subject.With(include => + { + AttributesInMansionResponse attributes = include.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(mansion.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(mansion.NumberOfResidents); + attributes.OwnerName.Should().Be(mansion.OwnerName); + + RelationshipsInMansionResponse relationships = include.Relationships.Should().BeOfType().Subject; + + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().HaveCount(3); + relationships.Rooms.Data.OfType().Should().ContainSingle(data => data.Id == mansionKitchenId); + relationships.Rooms.Data.OfType().Should().ContainSingle(data => data.Id == mansionBathroomId); + relationships.Rooms.Data.OfType().Should().ContainSingle(data => data.Id == mansionToiletId); + }); + + response.Included.OfType().Should().ContainSingle(include => include.Id == residence.StringId).Subject.With(include => + { + AttributesInResidenceResponse attributes = include.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(residence.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(residence.NumberOfResidents); + + RelationshipsInResidenceResponse relationships = include.Relationships.Should().BeOfType().Subject; + + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().HaveCount(1); + relationships.Rooms.Data.OfType().Should().ContainSingle(data => data.Id == residenceBedroomId); + }); + + response.Included.OfType().Should().ContainSingle(include => include.Id == familyHomeLivingRoomId); + response.Included.OfType().Should().ContainSingle(include => include.Id == familyRoomBedroomId); + response.Included.OfType().Should().ContainSingle(include => include.Id == mansionKitchenId); + response.Included.OfType().Should().ContainSingle(include => include.Id == mansionBathroomId); + response.Included.OfType().Should().ContainSingle(include => include.Id == mansionToiletId); + response.Included.OfType().Should().ContainSingle(include => include.Id == residenceBedroomId); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/CreateResourceTests.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/CreateResourceTests.cs new file mode 100644 index 0000000000..fca3f36228 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/CreateResourceTests.cs @@ -0,0 +1,220 @@ +using System.Net; +using FluentAssertions; +using Microsoft.EntityFrameworkCore; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.RestrictedControllers; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.RestrictedControllers; + +public sealed class CreateResourceTests : IClassFixture, RestrictionDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, RestrictionDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly RestrictionFakers _fakers = new(); + + public CreateResourceTests(IntegrationTestContext, RestrictionDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseController(); + } + + [Fact] + public async Task Can_create_resource_with_includes_and_fieldsets() + { + // Arrange + DataStream existingVideoStream = _fakers.DataStream.GenerateOne(); + DataStream existingAudioStream = _fakers.DataStream.GenerateOne(); + WriteOnlyChannel newChannel = _fakers.WriteOnlyChannel.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.DataStreams.AddRange(existingVideoStream, existingAudioStream); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + var requestBody = new CreateWriteOnlyChannelRequestDocument + { + Data = new DataInCreateWriteOnlyChannelRequest + { + Type = ResourceType.WriteOnlyChannels, + Attributes = new AttributesInCreateWriteOnlyChannelRequest + { + Name = newChannel.Name, + IsAdultOnly = newChannel.IsAdultOnly + }, + Relationships = new RelationshipsInCreateWriteOnlyChannelRequest + { + VideoStream = new ToOneDataStreamInRequest + { + Data = new DataStreamIdentifierInRequest + { + Type = ResourceType.DataStreams, + Id = existingVideoStream.StringId! + } + }, + AudioStreams = new ToManyDataStreamInRequest + { + Data = + [ + new DataStreamIdentifierInRequest + { + Type = ResourceType.DataStreams, + Id = existingAudioStream.StringId! + } + ] + } + } + } + }; + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["include"] = "videoStream,audioStreams", + ["fields[writeOnlyChannels]"] = "name,isCommercial,videoStream,audioStreams", + ["fields[dataStreams]"] = "bytesTransmitted" + }); + + // Act + PrimaryWriteOnlyChannelResponseDocument? response = await apiClient.WriteOnlyChannels.PostAsync(requestBody); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().NotBeNull(); + response.Data.Attributes.Should().NotBeNull(); + response.Data.Attributes.Name.Should().Be(newChannel.Name); + response.Data.Attributes.IsCommercial.Should().BeNull(); + response.Data.Attributes.IsAdultOnly.Should().BeNull(); + response.Data.Relationships.Should().NotBeNull(); + response.Data.Relationships.VideoStream.Should().NotBeNull(); + response.Data.Relationships.VideoStream.Data.Should().NotBeNull(); + response.Data.Relationships.VideoStream.Data.Id.Should().Be(existingVideoStream.StringId); + response.Data.Relationships.UltraHighDefinitionVideoStream.Should().BeNull(); + response.Data.Relationships.AudioStreams.Should().NotBeNull(); + response.Data.Relationships.AudioStreams.Data.Should().HaveCount(1); + response.Data.Relationships.AudioStreams.Data.ElementAt(0).Id.Should().Be(existingAudioStream.StringId); + + response.Included.Should().HaveCount(2); + + response.Included.OfType().Should().ContainSingle(include => include.Id == existingVideoStream.StringId).Subject.With( + include => + { + include.Attributes.Should().NotBeNull(); + include.Attributes.BytesTransmitted.Should().Be((long?)existingVideoStream.BytesTransmitted); + }); + + response.Included.OfType().Should().ContainSingle(include => include.Id == existingAudioStream.StringId).Subject.With( + include => + { + include.Attributes.Should().NotBeNull(); + include.Attributes.BytesTransmitted.Should().Be((long?)existingAudioStream.BytesTransmitted); + }); + + long newChannelId = long.Parse(response.Data.Id.Should().NotBeNull().And.Subject); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + // @formatter:wrap_chained_method_calls chop_always + // @formatter:keep_existing_linebreaks true + + WriteOnlyChannel channelInDatabase = await dbContext.WriteOnlyChannels + .Include(channel => channel.VideoStream) + .Include(channel => channel.AudioStreams) + .FirstWithIdAsync(newChannelId); + + // @formatter:keep_existing_linebreaks restore + // @formatter:wrap_chained_method_calls restore + + channelInDatabase.Name.Should().Be(newChannel.Name); + channelInDatabase.IsCommercial.Should().BeNull(); + channelInDatabase.IsAdultOnly.Should().Be(newChannel.IsAdultOnly); + + channelInDatabase.VideoStream.Should().NotBeNull(); + channelInDatabase.VideoStream.Id.Should().Be(existingVideoStream.Id); + + channelInDatabase.AudioStreams.Should().HaveCount(1); + channelInDatabase.AudioStreams.ElementAt(0).Id.Should().Be(existingAudioStream.Id); + }); + } + + [Fact] + public async Task Cannot_create_resource_for_missing_request_body() + { + // Arrange + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + CreateWriteOnlyChannelRequestDocument requestBody = null!; + + // Act + Func action = async () => _ = await apiClient.WriteOnlyChannels.PostAsync(requestBody); + + // Assert + await action.Should().ThrowExactlyAsync().WithParameterName("body"); + } + + [Fact] + public async Task Cannot_create_resource_with_unknown_relationship_ID() + { + // Arrange + WriteOnlyChannel newChannel = _fakers.WriteOnlyChannel.GenerateOne(); + + string unknownVideoStreamId = Unknown.StringId.For(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + var requestBody = new CreateWriteOnlyChannelRequestDocument + { + Data = new DataInCreateWriteOnlyChannelRequest + { + Type = ResourceType.WriteOnlyChannels, + Attributes = new AttributesInCreateWriteOnlyChannelRequest + { + Name = newChannel.Name + }, + Relationships = new RelationshipsInCreateWriteOnlyChannelRequest + { + VideoStream = new ToOneDataStreamInRequest + { + Data = new DataStreamIdentifierInRequest + { + Type = ResourceType.DataStreams, + Id = unknownVideoStreamId + } + } + } + } + }; + + // Act + Func action = async () => _ = await apiClient.WriteOnlyChannels.PostAsync(requestBody); + + // Assert + ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync()).Which; + exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.NotFound); + exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown."); + exception.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Errors.ElementAt(0); + error.Status.Should().Be("404"); + error.Title.Should().Be("A related resource does not exist."); + error.Detail.Should().Be($"Related resource of type 'dataStreams' with ID '{unknownVideoStreamId}' in relationship 'videoStream' does not exist."); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/DeleteResourceTests.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/DeleteResourceTests.cs new file mode 100644 index 0000000000..c19672be0b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/DeleteResourceTests.cs @@ -0,0 +1,85 @@ +using System.Net; +using FluentAssertions; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.RestrictedControllers; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.RestrictedControllers; + +public sealed class DeleteResourceTests : IClassFixture, RestrictionDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, RestrictionDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly RestrictionFakers _fakers = new(); + + public DeleteResourceTests(IntegrationTestContext, RestrictionDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseController(); + } + + [Fact] + public async Task Can_delete_existing_resource() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + // Act + await apiClient.WriteOnlyChannels[existingChannel.StringId!].DeleteAsync(); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + WriteOnlyChannel? channelInDatabase = await dbContext.WriteOnlyChannels.FirstWithIdOrDefaultAsync(existingChannel.Id); + + channelInDatabase.Should().BeNull(); + }); + } + + [Fact] + public async Task Cannot_delete_unknown_resource() + { + // Arrange + string unknownChannelId = Unknown.StringId.For(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + // Act + Func action = async () => await apiClient.WriteOnlyChannels[unknownChannelId].DeleteAsync(); + + // Assert + ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync()).Which; + exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.NotFound); + exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown."); + exception.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Errors.ElementAt(0); + error.Status.Should().Be("404"); + error.Title.Should().Be("The requested resource does not exist."); + error.Detail.Should().Be($"Resource of type 'writeOnlyChannels' with ID '{unknownChannelId}' does not exist."); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/FetchRelationshipTests.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/FetchRelationshipTests.cs new file mode 100644 index 0000000000..9baa1d0f3e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/FetchRelationshipTests.cs @@ -0,0 +1,158 @@ +using System.Net; +using FluentAssertions; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.RestrictedControllers; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.RestrictedControllers; + +public sealed class FetchRelationshipTests : IClassFixture, RestrictionDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, RestrictionDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly RestrictionFakers _fakers = new(); + + public FetchRelationshipTests(IntegrationTestContext, RestrictionDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseController(); + } + + [Fact] + public async Task Can_get_ToOne_relationship() + { + // Arrange + ReadOnlyChannel channel = _fakers.ReadOnlyChannel.GenerateOne(); + channel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.ReadOnlyChannels.Add(channel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + // Act + DataStreamIdentifierResponseDocument? response = await apiClient.ReadOnlyChannels[channel.StringId!].Relationships.VideoStream.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().NotBeNull(); + response.Data.Id.Should().Be(channel.VideoStream.StringId); + } + + [Fact] + public async Task Can_get_empty_ToOne_relationship() + { + // Arrange + ReadOnlyChannel channel = _fakers.ReadOnlyChannel.GenerateOne(); + channel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.ReadOnlyChannels.Add(channel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + // Act + NullableDataStreamIdentifierResponseDocument? response = + await apiClient.ReadOnlyChannels[channel.StringId!].Relationships.UltraHighDefinitionVideoStream.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().BeNull(); + } + + [Fact] + public async Task Can_get_ToMany_relationship() + { + // Arrange + ReadOnlyChannel channel = _fakers.ReadOnlyChannel.GenerateOne(); + channel.VideoStream = _fakers.DataStream.GenerateOne(); + channel.AudioStreams = _fakers.DataStream.GenerateSet(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.ReadOnlyChannels.Add(channel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + // Act + DataStreamIdentifierCollectionResponseDocument? response = await apiClient.ReadOnlyChannels[channel.StringId!].Relationships.AudioStreams.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(2); + response.Data.Should().ContainSingle(autoStream => autoStream.Id == channel.AudioStreams.ElementAt(0).StringId); + response.Data.Should().ContainSingle(autoStream => autoStream.Id == channel.AudioStreams.ElementAt(1).StringId); + } + + [Fact] + public async Task Can_get_empty_ToMany_relationship() + { + // Arrange + ReadOnlyChannel channel = _fakers.ReadOnlyChannel.GenerateOne(); + channel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.ReadOnlyChannels.Add(channel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + // Act + DataStreamIdentifierCollectionResponseDocument? response = await apiClient.ReadOnlyChannels[channel.StringId!].Relationships.AudioStreams.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(0); + } + + [Fact] + public async Task Cannot_get_relationship_for_unknown_primary_ID() + { + // Arrange + string unknownChannelId = Unknown.StringId.For(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + // Act + Func action = async () => _ = await apiClient.ReadOnlyChannels[unknownChannelId].Relationships.VideoStream.GetAsync(); + + // Assert + ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync()).Which; + exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.NotFound); + exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown."); + exception.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Errors.ElementAt(0); + error.Status.Should().Be("404"); + error.Title.Should().Be("The requested resource does not exist."); + error.Detail.Should().Be($"Resource of type 'readOnlyChannels' with ID '{unknownChannelId}' does not exist."); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/FetchResourceTests.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/FetchResourceTests.cs new file mode 100644 index 0000000000..05609f502e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/FetchResourceTests.cs @@ -0,0 +1,276 @@ +using System.Net; +using FluentAssertions; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.RestrictedControllers; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.RestrictedControllers; + +public sealed class FetchResourceTests : IClassFixture, RestrictionDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, RestrictionDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly RestrictionFakers _fakers = new(); + + public FetchResourceTests(IntegrationTestContext, RestrictionDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseController(); + } + + [Fact] + public async Task Can_get_primary_resources() + { + // Arrange + List channels = _fakers.ReadOnlyChannel.GenerateList(2); + channels.ForEach(channel => channel.VideoStream = _fakers.DataStream.GenerateOne()); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.ReadOnlyChannels.AddRange(channels); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + // Act + ReadOnlyChannelCollectionResponseDocument? response = await apiClient.ReadOnlyChannels.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(2); + + DataInReadOnlyChannelResponse channel1 = response.Data.Single(channel => channel.Id == channels.ElementAt(0).StringId); + channel1.Attributes.Should().NotBeNull(); + channel1.Attributes.Name.Should().Be(channels[0].Name); + channel1.Attributes.IsCommercial.Should().Be(channels[0].IsCommercial); + channel1.Attributes.IsAdultOnly.Should().Be(channels[0].IsAdultOnly); + channel1.Relationships.Should().NotBeNull(); + channel1.Relationships.VideoStream.Should().NotBeNull(); + channel1.Relationships.VideoStream.Data.Should().BeNull(); + channel1.Relationships.UltraHighDefinitionVideoStream.Should().NotBeNull(); + channel1.Relationships.UltraHighDefinitionVideoStream.Data.Should().BeNull(); + channel1.Relationships.AudioStreams.Should().NotBeNull(); + channel1.Relationships.AudioStreams.Data.Should().BeNull(); + + DataInReadOnlyChannelResponse channel2 = response.Data.Single(channel => channel.Id == channels.ElementAt(1).StringId); + channel2.Attributes.Should().NotBeNull(); + channel2.Attributes.Name.Should().Be(channels[1].Name); + channel2.Attributes.IsCommercial.Should().Be(channels[1].IsCommercial); + channel2.Attributes.IsAdultOnly.Should().Be(channels[1].IsAdultOnly); + channel2.Relationships.Should().NotBeNull(); + channel2.Relationships.VideoStream.Should().NotBeNull(); + channel2.Relationships.VideoStream.Data.Should().BeNull(); + channel2.Relationships.UltraHighDefinitionVideoStream.Should().NotBeNull(); + channel2.Relationships.UltraHighDefinitionVideoStream.Data.Should().BeNull(); + channel2.Relationships.AudioStreams.Should().NotBeNull(); + channel2.Relationships.AudioStreams.Data.Should().BeNull(); + } + + [Fact] + public async Task Can_get_primary_resource_by_ID() + { + // Arrange + ReadOnlyChannel channel = _fakers.ReadOnlyChannel.GenerateOne(); + channel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.ReadOnlyChannels.Add(channel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + // Act + PrimaryReadOnlyChannelResponseDocument? response = await apiClient.ReadOnlyChannels[channel.StringId!].GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().NotBeNull(); + response.Data.Id.Should().Be(channel.StringId); + response.Data.Attributes.Should().NotBeNull(); + response.Data.Attributes.Name.Should().Be(channel.Name); + response.Data.Attributes.IsCommercial.Should().Be(channel.IsCommercial); + response.Data.Attributes.IsAdultOnly.Should().Be(channel.IsAdultOnly); + response.Data.Relationships.Should().NotBeNull(); + response.Data.Relationships.VideoStream.Should().NotBeNull(); + response.Data.Relationships.VideoStream.Data.Should().BeNull(); + response.Data.Relationships.UltraHighDefinitionVideoStream.Should().NotBeNull(); + response.Data.Relationships.UltraHighDefinitionVideoStream.Data.Should().BeNull(); + response.Data.Relationships.AudioStreams.Should().NotBeNull(); + response.Data.Relationships.AudioStreams.Data.Should().BeNull(); + } + + [Fact] + public async Task Cannot_get_primary_resource_for_unknown_ID() + { + // Arrange + string unknownChannelId = Unknown.StringId.For(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + // Act + Func action = async () => _ = await apiClient.ReadOnlyChannels[unknownChannelId].GetAsync(); + + // Assert + ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync()).Which; + exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.NotFound); + exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown."); + exception.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Errors.ElementAt(0); + error.Status.Should().Be("404"); + error.Title.Should().Be("The requested resource does not exist."); + error.Detail.Should().Be($"Resource of type 'readOnlyChannels' with ID '{unknownChannelId}' does not exist."); + } + + [Fact] + public async Task Can_get_secondary_ToOne_resource() + { + // Arrange + ReadOnlyChannel channel = _fakers.ReadOnlyChannel.GenerateOne(); + channel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.ReadOnlyChannels.Add(channel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + // Act + SecondaryDataStreamResponseDocument? response = await apiClient.ReadOnlyChannels[channel.StringId!].VideoStream.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().NotBeNull(); + response.Data.Id.Should().Be(channel.VideoStream.StringId); + response.Data.Attributes.Should().NotBeNull(); + response.Data.Attributes.BytesTransmitted.Should().Be((long?)channel.VideoStream.BytesTransmitted); + } + + [Fact] + public async Task Can_get_unknown_secondary_ToOne_resource() + { + // Arrange + ReadOnlyChannel channel = _fakers.ReadOnlyChannel.GenerateOne(); + channel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.ReadOnlyChannels.Add(channel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + // Act + NullableSecondaryDataStreamResponseDocument? response = await apiClient.ReadOnlyChannels[channel.StringId!].UltraHighDefinitionVideoStream.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().BeNull(); + } + + [Fact] + public async Task Can_get_secondary_ToMany_resources() + { + // Arrange + ReadOnlyChannel channel = _fakers.ReadOnlyChannel.GenerateOne(); + channel.VideoStream = _fakers.DataStream.GenerateOne(); + channel.AudioStreams = _fakers.DataStream.GenerateSet(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.ReadOnlyChannels.Add(channel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + // Act + DataStreamCollectionResponseDocument? response = await apiClient.ReadOnlyChannels[channel.StringId!].AudioStreams.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(2); + + DataInDataStreamResponse audioStream1 = response.Data.Single(autoStream => autoStream.Id == channel.AudioStreams.ElementAt(0).StringId); + audioStream1.Attributes.Should().NotBeNull(); + audioStream1.Attributes.BytesTransmitted.Should().Be((long?)channel.AudioStreams.ElementAt(0).BytesTransmitted); + + DataInDataStreamResponse audioStream2 = response.Data.Single(autoStream => autoStream.Id == channel.AudioStreams.ElementAt(1).StringId); + audioStream2.Attributes.Should().NotBeNull(); + audioStream2.Attributes.BytesTransmitted.Should().Be((long?)channel.AudioStreams.ElementAt(1).BytesTransmitted); + } + + [Fact] + public async Task Can_get_no_secondary_ToMany_resources() + { + // Arrange + ReadOnlyChannel channel = _fakers.ReadOnlyChannel.GenerateOne(); + channel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.ReadOnlyChannels.Add(channel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + // Act + DataStreamCollectionResponseDocument? response = await apiClient.ReadOnlyChannels[channel.StringId!].AudioStreams.GetAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(0); + } + + [Fact] + public async Task Cannot_get_secondary_resource_for_unknown_primary_ID() + { + // Arrange + string unknownChannelId = Unknown.StringId.For(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + // Act + Func action = async () => _ = await apiClient.ReadOnlyChannels[unknownChannelId].VideoStream.GetAsync(); + + // Assert + ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync()).Which; + exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.NotFound); + exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown."); + exception.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Errors.ElementAt(0); + error.Status.Should().Be("404"); + error.Title.Should().Be("The requested resource does not exist."); + error.Detail.Should().Be($"Resource of type 'readOnlyChannels' with ID '{unknownChannelId}' does not exist."); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/DataStreams/DataStreamsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/DataStreams/DataStreamsRequestBuilder.cs new file mode 100644 index 0000000000..ac1fb093a5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/DataStreams/DataStreamsRequestBuilder.cs @@ -0,0 +1,140 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.DataStreams.Item; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.DataStreams +{ + /// + /// Builds and executes requests for operations under \dataStreams + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class DataStreamsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.dataStreams.item collection + /// The identifier of the dataStream to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.DataStreams.Item.DataStreamsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.DataStreams.Item.DataStreamsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public DataStreamsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/dataStreams{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public DataStreamsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/dataStreams{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of dataStreams. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of dataStreams. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.DataStreams.DataStreamsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.DataStreams.DataStreamsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of dataStreams. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class DataStreamsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class DataStreamsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/DataStreams/Item/DataStreamsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/DataStreams/Item/DataStreamsItemRequestBuilder.cs new file mode 100644 index 0000000000..9dd3d5b5ba --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/DataStreams/Item/DataStreamsItemRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.DataStreams.Item +{ + /// + /// Builds and executes requests for operations under \dataStreams\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class DataStreamsItemRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public DataStreamsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/dataStreams/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public DataStreamsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/dataStreams/{id}{?query*}", rawUrl) + { + } + + /// + /// Retrieves an individual dataStream by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.PrimaryDataStreamResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual dataStream by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.DataStreams.Item.DataStreamsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.DataStreams.Item.DataStreamsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual dataStream by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class DataStreamsItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class DataStreamsItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInCreateRequest.cs new file mode 100644 index 0000000000..af38053ddf --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInCreateRequest.cs @@ -0,0 +1,75 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "writeOnlyChannels" => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInCreateWriteOnlyChannelRequest(), + _ => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInCreateWriteOnlyChannelRequest.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInCreateWriteOnlyChannelRequest.cs new file mode 100644 index 0000000000..d500c4990b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInCreateWriteOnlyChannelRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInCreateWriteOnlyChannelRequest : global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The isAdultOnly property + public bool? IsAdultOnly + { + get { return BackingStore?.Get("isAdultOnly"); } + set { BackingStore?.Set("isAdultOnly", value); } + } + + /// The isCommercial property + public bool? IsCommercial + { + get { return BackingStore?.Get("isCommercial"); } + set { BackingStore?.Set("isCommercial", value); } + } + + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInCreateWriteOnlyChannelRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInCreateWriteOnlyChannelRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "isAdultOnly", n => { IsAdultOnly = n.GetBoolValue(); } }, + { "isCommercial", n => { IsCommercial = n.GetBoolValue(); } }, + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("isAdultOnly", IsAdultOnly); + writer.WriteBoolValue("isCommercial", IsCommercial); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInDataStreamResponse.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInDataStreamResponse.cs new file mode 100644 index 0000000000..4a9f5d811e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInDataStreamResponse.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInDataStreamResponse : global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The bytesTransmitted property + public long? BytesTransmitted + { + get { return BackingStore?.Get("bytesTransmitted"); } + set { BackingStore?.Set("bytesTransmitted", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInDataStreamResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInDataStreamResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "bytesTransmitted", n => { BytesTransmitted = n.GetLongValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteLongValue("bytesTransmitted", BytesTransmitted); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInReadOnlyChannelResponse.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInReadOnlyChannelResponse.cs new file mode 100644 index 0000000000..bfee76bc49 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInReadOnlyChannelResponse.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInReadOnlyChannelResponse : global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The isAdultOnly property + public bool? IsAdultOnly + { + get { return BackingStore?.Get("isAdultOnly"); } + set { BackingStore?.Set("isAdultOnly", value); } + } + + /// The isCommercial property + public bool? IsCommercial + { + get { return BackingStore?.Get("isCommercial"); } + set { BackingStore?.Set("isCommercial", value); } + } + + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInReadOnlyChannelResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInReadOnlyChannelResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "isAdultOnly", n => { IsAdultOnly = n.GetBoolValue(); } }, + { "isCommercial", n => { IsCommercial = n.GetBoolValue(); } }, + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("isAdultOnly", IsAdultOnly); + writer.WriteBoolValue("isCommercial", IsCommercial); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInReadOnlyResourceChannelResponse.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInReadOnlyResourceChannelResponse.cs new file mode 100644 index 0000000000..7693212745 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInReadOnlyResourceChannelResponse.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInReadOnlyResourceChannelResponse : global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The isAdultOnly property + public bool? IsAdultOnly + { + get { return BackingStore?.Get("isAdultOnly"); } + set { BackingStore?.Set("isAdultOnly", value); } + } + + /// The isCommercial property + public bool? IsCommercial + { + get { return BackingStore?.Get("isCommercial"); } + set { BackingStore?.Set("isCommercial", value); } + } + + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInReadOnlyResourceChannelResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInReadOnlyResourceChannelResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "isAdultOnly", n => { IsAdultOnly = n.GetBoolValue(); } }, + { "isCommercial", n => { IsCommercial = n.GetBoolValue(); } }, + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("isAdultOnly", IsAdultOnly); + writer.WriteBoolValue("isCommercial", IsCommercial); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInResponse.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInResponse.cs new file mode 100644 index 0000000000..a239b32c64 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInResponse.cs @@ -0,0 +1,78 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "dataStreams" => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInDataStreamResponse(), + "readOnlyChannels" => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInReadOnlyChannelResponse(), + "readOnlyResourceChannels" => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInReadOnlyResourceChannelResponse(), + "writeOnlyChannels" => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInWriteOnlyChannelResponse(), + _ => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInUpdateRequest.cs new file mode 100644 index 0000000000..b03000812c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInUpdateRequest.cs @@ -0,0 +1,75 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public AttributesInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "writeOnlyChannels" => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInUpdateWriteOnlyChannelRequest(), + _ => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInUpdateWriteOnlyChannelRequest.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInUpdateWriteOnlyChannelRequest.cs new file mode 100644 index 0000000000..58b46afa4a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInUpdateWriteOnlyChannelRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInUpdateWriteOnlyChannelRequest : global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The isAdultOnly property + public bool? IsAdultOnly + { + get { return BackingStore?.Get("isAdultOnly"); } + set { BackingStore?.Set("isAdultOnly", value); } + } + + /// The isCommercial property + public bool? IsCommercial + { + get { return BackingStore?.Get("isCommercial"); } + set { BackingStore?.Set("isCommercial", value); } + } + + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInUpdateWriteOnlyChannelRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInUpdateWriteOnlyChannelRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "isAdultOnly", n => { IsAdultOnly = n.GetBoolValue(); } }, + { "isCommercial", n => { IsCommercial = n.GetBoolValue(); } }, + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("isAdultOnly", IsAdultOnly); + writer.WriteBoolValue("isCommercial", IsCommercial); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInWriteOnlyChannelResponse.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInWriteOnlyChannelResponse.cs new file mode 100644 index 0000000000..e9d0d2aa3f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/AttributesInWriteOnlyChannelResponse.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class AttributesInWriteOnlyChannelResponse : global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInResponse, IParsable + #pragma warning restore CS1591 + { + /// The isAdultOnly property + public bool? IsAdultOnly + { + get { return BackingStore?.Get("isAdultOnly"); } + set { BackingStore?.Set("isAdultOnly", value); } + } + + /// The isCommercial property + public bool? IsCommercial + { + get { return BackingStore?.Get("isCommercial"); } + set { BackingStore?.Set("isCommercial", value); } + } + + /// The name property + public string? Name + { + get { return BackingStore?.Get("name"); } + set { BackingStore?.Set("name", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInWriteOnlyChannelResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInWriteOnlyChannelResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "isAdultOnly", n => { IsAdultOnly = n.GetBoolValue(); } }, + { "isCommercial", n => { IsCommercial = n.GetBoolValue(); } }, + { "name", n => { Name = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteBoolValue("isAdultOnly", IsAdultOnly); + writer.WriteBoolValue("isCommercial", IsCommercial); + writer.WriteStringValue("name", Name); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/CreateWriteOnlyChannelRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/CreateWriteOnlyChannelRequestDocument.cs new file mode 100644 index 0000000000..dc38870255 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/CreateWriteOnlyChannelRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class CreateWriteOnlyChannelRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInCreateWriteOnlyChannelRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public CreateWriteOnlyChannelRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.CreateWriteOnlyChannelRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.CreateWriteOnlyChannelRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInCreateWriteOnlyChannelRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataInCreateWriteOnlyChannelRequest.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataInCreateWriteOnlyChannelRequest.cs new file mode 100644 index 0000000000..77478b5490 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataInCreateWriteOnlyChannelRequest.cs @@ -0,0 +1,68 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInCreateWriteOnlyChannelRequest : global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInCreateWriteOnlyChannelRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInCreateWriteOnlyChannelRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInCreateWriteOnlyChannelRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInCreateWriteOnlyChannelRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInCreateWriteOnlyChannelRequest.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInCreateWriteOnlyChannelRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataInDataStreamResponse.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataInDataStreamResponse.cs new file mode 100644 index 0000000000..c139f58730 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataInDataStreamResponse.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInDataStreamResponse : global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInDataStreamResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInDataStreamResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInDataStreamResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInDataStreamResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataInReadOnlyChannelResponse.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataInReadOnlyChannelResponse.cs new file mode 100644 index 0000000000..f58e182a63 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataInReadOnlyChannelResponse.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInReadOnlyChannelResponse : global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInReadOnlyChannelResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInReadOnlyChannelResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInReadOnlyChannelResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInReadOnlyChannelResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInReadOnlyChannelResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInReadOnlyChannelResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataInReadOnlyResourceChannelResponse.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataInReadOnlyResourceChannelResponse.cs new file mode 100644 index 0000000000..5ab70abf76 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataInReadOnlyResourceChannelResponse.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInReadOnlyResourceChannelResponse : global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInReadOnlyResourceChannelResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInReadOnlyResourceChannelResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInReadOnlyResourceChannelResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInReadOnlyResourceChannelResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInReadOnlyResourceChannelResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInReadOnlyResourceChannelResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataInUpdateWriteOnlyChannelRequest.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataInUpdateWriteOnlyChannelRequest.cs new file mode 100644 index 0000000000..8972625339 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataInUpdateWriteOnlyChannelRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInUpdateWriteOnlyChannelRequest : global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInUpdateWriteOnlyChannelRequest? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInUpdateWriteOnlyChannelRequest? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInUpdateWriteOnlyChannelRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInUpdateWriteOnlyChannelRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInUpdateWriteOnlyChannelRequest.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInUpdateWriteOnlyChannelRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataInWriteOnlyChannelResponse.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataInWriteOnlyChannelResponse.cs new file mode 100644 index 0000000000..6ddd971254 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataInWriteOnlyChannelResponse.cs @@ -0,0 +1,86 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataInWriteOnlyChannelResponse : global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceInResponse, IParsable + #pragma warning restore CS1591 + { + /// The attributes property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInWriteOnlyChannelResponse? Attributes + { + get { return BackingStore?.Get("attributes"); } + set { BackingStore?.Set("attributes", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInWriteOnlyChannelResponse? Relationships + { + get { return BackingStore?.Get("relationships"); } + set { BackingStore?.Set("relationships", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInWriteOnlyChannelResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInWriteOnlyChannelResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "attributes", n => { Attributes = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.AttributesInWriteOnlyChannelResponse.CreateFromDiscriminatorValue); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceLinks.CreateFromDiscriminatorValue); } }, + { "relationships", n => { Relationships = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInWriteOnlyChannelResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("attributes", Attributes); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("relationships", Relationships); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataStreamCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataStreamCollectionResponseDocument.cs new file mode 100644 index 0000000000..dd2010b42d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataStreamCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataStreamCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public DataStreamCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInDataStreamResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataStreamIdentifierCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataStreamIdentifierCollectionResponseDocument.cs new file mode 100644 index 0000000000..f42235a0d9 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataStreamIdentifierCollectionResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataStreamIdentifierCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public DataStreamIdentifierCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataStreamIdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataStreamIdentifierInRequest.cs new file mode 100644 index 0000000000..cd7a7ff59b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataStreamIdentifierInRequest.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataStreamIdentifierInRequest : global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.IdentifierInRequest, IParsable + #pragma warning restore CS1591 + { + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "id", n => { Id = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteStringValue("id", Id); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataStreamIdentifierInResponse.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataStreamIdentifierInResponse.cs new file mode 100644 index 0000000000..68a87760b8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataStreamIdentifierInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataStreamIdentifierInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public DataStreamIdentifierInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "id", n => { Id = n.GetStringValue(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataStreamIdentifierResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataStreamIdentifierResponseDocument.cs new file mode 100644 index 0000000000..5ae636804a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataStreamIdentifierResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class DataStreamIdentifierResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceIdentifierTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public DataStreamIdentifierResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceIdentifierTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataStreamResourceType.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataStreamResourceType.cs new file mode 100644 index 0000000000..8e460d0149 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/DataStreamResourceType.cs @@ -0,0 +1,18 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum DataStreamResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "dataStreams")] + #pragma warning disable CS1591 + DataStreams, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ErrorLinks.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ErrorLinks.cs new file mode 100644 index 0000000000..f476915be7 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ErrorLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// The about property + public string? About + { + get { return BackingStore?.Get("about"); } + set { BackingStore?.Set("about", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The type property + public string? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "about", n => { About = n.GetStringValue(); } }, + { "type", n => { Type = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("about", About); + writer.WriteStringValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ErrorObject.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ErrorObject.cs new file mode 100644 index 0000000000..3cb6a00b41 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ErrorObject.cs @@ -0,0 +1,133 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorObject : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The code property + public string? Code + { + get { return BackingStore?.Get("code"); } + set { BackingStore?.Set("code", value); } + } + + /// The detail property + public string? Detail + { + get { return BackingStore?.Get("detail"); } + set { BackingStore?.Set("detail", value); } + } + + /// The id property + public string? Id + { + get { return BackingStore?.Get("id"); } + set { BackingStore?.Set("id", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The source property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorSource? Source + { + get { return BackingStore?.Get("source"); } + set { BackingStore?.Set("source", value); } + } + + /// The status property + public string? Status + { + get { return BackingStore?.Get("status"); } + set { BackingStore?.Set("status", value); } + } + + /// The title property + public string? Title + { + get { return BackingStore?.Get("title"); } + set { BackingStore?.Set("title", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorObject() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorObject CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorObject(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "code", n => { Code = n.GetStringValue(); } }, + { "detail", n => { Detail = n.GetStringValue(); } }, + { "id", n => { Id = n.GetStringValue(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "source", n => { Source = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorSource.CreateFromDiscriminatorValue); } }, + { "status", n => { Status = n.GetStringValue(); } }, + { "title", n => { Title = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("code", Code); + writer.WriteStringValue("detail", Detail); + writer.WriteStringValue("id", Id); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + writer.WriteObjectValue("source", Source); + writer.WriteStringValue("status", Status); + writer.WriteStringValue("title", Title); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ErrorResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ErrorResponseDocument.cs new file mode 100644 index 0000000000..2bc9decaeb --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ErrorResponseDocument.cs @@ -0,0 +1,92 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorResponseDocument : ApiException, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The errors property + public List? Errors + { + get { return BackingStore?.Get?>("errors"); } + set { BackingStore?.Set("errors", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The primary error message. + public override string Message { get => base.Message; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "errors", n => { Errors = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorObject.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("errors", Errors); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ErrorSource.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ErrorSource.cs new file mode 100644 index 0000000000..47814e19f2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ErrorSource.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorSource : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The header property + public string? Header + { + get { return BackingStore?.Get("header"); } + set { BackingStore?.Set("header", value); } + } + + /// The parameter property + public string? Parameter + { + get { return BackingStore?.Get("parameter"); } + set { BackingStore?.Set("parameter", value); } + } + + /// The pointer property + public string? Pointer + { + get { return BackingStore?.Get("pointer"); } + set { BackingStore?.Set("pointer", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorSource() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorSource CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorSource(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "header", n => { Header = n.GetStringValue(); } }, + { "parameter", n => { Parameter = n.GetStringValue(); } }, + { "pointer", n => { Pointer = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("header", Header); + writer.WriteStringValue("parameter", Parameter); + writer.WriteStringValue("pointer", Pointer); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ErrorTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ErrorTopLevelLinks.cs new file mode 100644 index 0000000000..c88a314d2b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ErrorTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ErrorTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ErrorTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/IdentifierInRequest.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/IdentifierInRequest.cs new file mode 100644 index 0000000000..bd10e84a5b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/IdentifierInRequest.cs @@ -0,0 +1,84 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class IdentifierInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public IdentifierInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.IdentifierInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "dataStreams" => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierInRequest(), + _ => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.IdentifierInRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/Meta.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/Meta.cs new file mode 100644 index 0000000000..94ab7f2943 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/Meta.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class Meta : IAdditionalDataHolder, IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + public IDictionary AdditionalData + { + get { return BackingStore.Get>("AdditionalData") ?? new Dictionary(); } + set { BackingStore.Set("AdditionalData", value); } + } + + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// + /// Instantiates a new and sets the default values. + /// + public Meta() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + AdditionalData = new Dictionary(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteAdditionalData(AdditionalData); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/NullableDataStreamIdentifierResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/NullableDataStreamIdentifierResponseDocument.cs new file mode 100644 index 0000000000..7a0da274db --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/NullableDataStreamIdentifierResponseDocument.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NullableDataStreamIdentifierResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceIdentifierTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NullableDataStreamIdentifierResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableDataStreamIdentifierResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableDataStreamIdentifierResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceIdentifierTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/NullableSecondaryDataStreamResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/NullableSecondaryDataStreamResponseDocument.cs new file mode 100644 index 0000000000..e604e3f280 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/NullableSecondaryDataStreamResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NullableSecondaryDataStreamResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInDataStreamResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NullableSecondaryDataStreamResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableSecondaryDataStreamResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableSecondaryDataStreamResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInDataStreamResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/NullableToOneDataStreamInRequest.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/NullableToOneDataStreamInRequest.cs new file mode 100644 index 0000000000..e265d36fd0 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/NullableToOneDataStreamInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NullableToOneDataStreamInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierInRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NullableToOneDataStreamInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableToOneDataStreamInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableToOneDataStreamInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierInRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/NullableToOneDataStreamInResponse.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/NullableToOneDataStreamInResponse.cs new file mode 100644 index 0000000000..61a2e3409f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/NullableToOneDataStreamInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class NullableToOneDataStreamInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public NullableToOneDataStreamInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableToOneDataStreamInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableToOneDataStreamInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/PrimaryDataStreamResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/PrimaryDataStreamResponseDocument.cs new file mode 100644 index 0000000000..cd2eaa367c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/PrimaryDataStreamResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryDataStreamResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInDataStreamResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryDataStreamResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.PrimaryDataStreamResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.PrimaryDataStreamResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInDataStreamResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/PrimaryReadOnlyChannelResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/PrimaryReadOnlyChannelResponseDocument.cs new file mode 100644 index 0000000000..76ab55657b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/PrimaryReadOnlyChannelResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryReadOnlyChannelResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInReadOnlyChannelResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryReadOnlyChannelResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.PrimaryReadOnlyChannelResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.PrimaryReadOnlyChannelResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInReadOnlyChannelResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/PrimaryReadOnlyResourceChannelResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/PrimaryReadOnlyResourceChannelResponseDocument.cs new file mode 100644 index 0000000000..2e069325f4 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/PrimaryReadOnlyResourceChannelResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryReadOnlyResourceChannelResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInReadOnlyResourceChannelResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryReadOnlyResourceChannelResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.PrimaryReadOnlyResourceChannelResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.PrimaryReadOnlyResourceChannelResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInReadOnlyResourceChannelResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/PrimaryWriteOnlyChannelResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/PrimaryWriteOnlyChannelResponseDocument.cs new file mode 100644 index 0000000000..c28af81a2d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/PrimaryWriteOnlyChannelResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class PrimaryWriteOnlyChannelResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInWriteOnlyChannelResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public PrimaryWriteOnlyChannelResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.PrimaryWriteOnlyChannelResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.PrimaryWriteOnlyChannelResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInWriteOnlyChannelResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ReadOnlyChannelCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ReadOnlyChannelCollectionResponseDocument.cs new file mode 100644 index 0000000000..91820513d6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ReadOnlyChannelCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ReadOnlyChannelCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ReadOnlyChannelCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ReadOnlyChannelCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ReadOnlyChannelCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInReadOnlyChannelResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ReadOnlyResourceChannelCollectionResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ReadOnlyResourceChannelCollectionResponseDocument.cs new file mode 100644 index 0000000000..4f5b4d82c8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ReadOnlyResourceChannelCollectionResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ReadOnlyResourceChannelCollectionResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceCollectionTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ReadOnlyResourceChannelCollectionResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ReadOnlyResourceChannelCollectionResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ReadOnlyResourceChannelCollectionResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInReadOnlyResourceChannelResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceCollectionTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipLinks.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipLinks.cs new file mode 100644 index 0000000000..ffc24e6ed5 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInCreateRequest.cs new file mode 100644 index 0000000000..8362d04cb3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInCreateRequest.cs @@ -0,0 +1,75 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "writeOnlyChannels" => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInCreateWriteOnlyChannelRequest(), + _ => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInCreateWriteOnlyChannelRequest.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInCreateWriteOnlyChannelRequest.cs new file mode 100644 index 0000000000..0ce350dfa1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInCreateWriteOnlyChannelRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInCreateWriteOnlyChannelRequest : global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInCreateRequest, IParsable + #pragma warning restore CS1591 + { + /// The audioStreams property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInRequest? AudioStreams + { + get { return BackingStore?.Get("audioStreams"); } + set { BackingStore?.Set("audioStreams", value); } + } + + /// The ultraHighDefinitionVideoStream property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableToOneDataStreamInRequest? UltraHighDefinitionVideoStream + { + get { return BackingStore?.Get("ultraHighDefinitionVideoStream"); } + set { BackingStore?.Set("ultraHighDefinitionVideoStream", value); } + } + + /// The videoStream property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToOneDataStreamInRequest? VideoStream + { + get { return BackingStore?.Get("videoStream"); } + set { BackingStore?.Set("videoStream", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInCreateWriteOnlyChannelRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInCreateWriteOnlyChannelRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "audioStreams", n => { AudioStreams = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInRequest.CreateFromDiscriminatorValue); } }, + { "ultraHighDefinitionVideoStream", n => { UltraHighDefinitionVideoStream = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableToOneDataStreamInRequest.CreateFromDiscriminatorValue); } }, + { "videoStream", n => { VideoStream = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToOneDataStreamInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("audioStreams", AudioStreams); + writer.WriteObjectValue("ultraHighDefinitionVideoStream", UltraHighDefinitionVideoStream); + writer.WriteObjectValue("videoStream", VideoStream); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInReadOnlyChannelResponse.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInReadOnlyChannelResponse.cs new file mode 100644 index 0000000000..5c79ba3972 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInReadOnlyChannelResponse.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInReadOnlyChannelResponse : global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// The audioStreams property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInResponse? AudioStreams + { + get { return BackingStore?.Get("audioStreams"); } + set { BackingStore?.Set("audioStreams", value); } + } + + /// The ultraHighDefinitionVideoStream property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableToOneDataStreamInResponse? UltraHighDefinitionVideoStream + { + get { return BackingStore?.Get("ultraHighDefinitionVideoStream"); } + set { BackingStore?.Set("ultraHighDefinitionVideoStream", value); } + } + + /// The videoStream property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToOneDataStreamInResponse? VideoStream + { + get { return BackingStore?.Get("videoStream"); } + set { BackingStore?.Set("videoStream", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInReadOnlyChannelResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInReadOnlyChannelResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "audioStreams", n => { AudioStreams = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInResponse.CreateFromDiscriminatorValue); } }, + { "ultraHighDefinitionVideoStream", n => { UltraHighDefinitionVideoStream = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableToOneDataStreamInResponse.CreateFromDiscriminatorValue); } }, + { "videoStream", n => { VideoStream = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToOneDataStreamInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("audioStreams", AudioStreams); + writer.WriteObjectValue("ultraHighDefinitionVideoStream", UltraHighDefinitionVideoStream); + writer.WriteObjectValue("videoStream", VideoStream); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInReadOnlyResourceChannelResponse.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInReadOnlyResourceChannelResponse.cs new file mode 100644 index 0000000000..689da3eb21 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInReadOnlyResourceChannelResponse.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInReadOnlyResourceChannelResponse : global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// The audioStreams property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInResponse? AudioStreams + { + get { return BackingStore?.Get("audioStreams"); } + set { BackingStore?.Set("audioStreams", value); } + } + + /// The ultraHighDefinitionVideoStream property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableToOneDataStreamInResponse? UltraHighDefinitionVideoStream + { + get { return BackingStore?.Get("ultraHighDefinitionVideoStream"); } + set { BackingStore?.Set("ultraHighDefinitionVideoStream", value); } + } + + /// The videoStream property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToOneDataStreamInResponse? VideoStream + { + get { return BackingStore?.Get("videoStream"); } + set { BackingStore?.Set("videoStream", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInReadOnlyResourceChannelResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInReadOnlyResourceChannelResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "audioStreams", n => { AudioStreams = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInResponse.CreateFromDiscriminatorValue); } }, + { "ultraHighDefinitionVideoStream", n => { UltraHighDefinitionVideoStream = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableToOneDataStreamInResponse.CreateFromDiscriminatorValue); } }, + { "videoStream", n => { VideoStream = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToOneDataStreamInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("audioStreams", AudioStreams); + writer.WriteObjectValue("ultraHighDefinitionVideoStream", UltraHighDefinitionVideoStream); + writer.WriteObjectValue("videoStream", VideoStream); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInResponse.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInResponse.cs new file mode 100644 index 0000000000..787b6582c8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInResponse.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "readOnlyChannels" => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInReadOnlyChannelResponse(), + "readOnlyResourceChannels" => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInReadOnlyResourceChannelResponse(), + "writeOnlyChannels" => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInWriteOnlyChannelResponse(), + _ => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInUpdateRequest.cs new file mode 100644 index 0000000000..455267e937 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInUpdateRequest.cs @@ -0,0 +1,75 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The openapiDiscriminator property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceType? OpenapiDiscriminator + { + get { return BackingStore?.Get("openapi:discriminator"); } + set { BackingStore?.Set("openapi:discriminator", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public RelationshipsInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("openapi:discriminator")?.GetStringValue(); + return mappingValue switch + { + "writeOnlyChannels" => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInUpdateWriteOnlyChannelRequest(), + _ => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "openapi:discriminator", n => { OpenapiDiscriminator = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteEnumValue("openapi:discriminator", OpenapiDiscriminator); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInUpdateWriteOnlyChannelRequest.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInUpdateWriteOnlyChannelRequest.cs new file mode 100644 index 0000000000..cf520fbe85 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInUpdateWriteOnlyChannelRequest.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInUpdateWriteOnlyChannelRequest : global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInUpdateRequest, IParsable + #pragma warning restore CS1591 + { + /// The audioStreams property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInRequest? AudioStreams + { + get { return BackingStore?.Get("audioStreams"); } + set { BackingStore?.Set("audioStreams", value); } + } + + /// The ultraHighDefinitionVideoStream property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableToOneDataStreamInRequest? UltraHighDefinitionVideoStream + { + get { return BackingStore?.Get("ultraHighDefinitionVideoStream"); } + set { BackingStore?.Set("ultraHighDefinitionVideoStream", value); } + } + + /// The videoStream property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToOneDataStreamInRequest? VideoStream + { + get { return BackingStore?.Get("videoStream"); } + set { BackingStore?.Set("videoStream", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInUpdateWriteOnlyChannelRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInUpdateWriteOnlyChannelRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "audioStreams", n => { AudioStreams = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInRequest.CreateFromDiscriminatorValue); } }, + { "ultraHighDefinitionVideoStream", n => { UltraHighDefinitionVideoStream = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableToOneDataStreamInRequest.CreateFromDiscriminatorValue); } }, + { "videoStream", n => { VideoStream = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToOneDataStreamInRequest.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("audioStreams", AudioStreams); + writer.WriteObjectValue("ultraHighDefinitionVideoStream", UltraHighDefinitionVideoStream); + writer.WriteObjectValue("videoStream", VideoStream); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInWriteOnlyChannelResponse.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInWriteOnlyChannelResponse.cs new file mode 100644 index 0000000000..f46ec749de --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/RelationshipsInWriteOnlyChannelResponse.cs @@ -0,0 +1,77 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class RelationshipsInWriteOnlyChannelResponse : global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInResponse, IParsable + #pragma warning restore CS1591 + { + /// The audioStreams property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInResponse? AudioStreams + { + get { return BackingStore?.Get("audioStreams"); } + set { BackingStore?.Set("audioStreams", value); } + } + + /// The ultraHighDefinitionVideoStream property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableToOneDataStreamInResponse? UltraHighDefinitionVideoStream + { + get { return BackingStore?.Get("ultraHighDefinitionVideoStream"); } + set { BackingStore?.Set("ultraHighDefinitionVideoStream", value); } + } + + /// The videoStream property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToOneDataStreamInResponse? VideoStream + { + get { return BackingStore?.Get("videoStream"); } + set { BackingStore?.Set("videoStream", value); } + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInWriteOnlyChannelResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipsInWriteOnlyChannelResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public override IDictionary> GetFieldDeserializers() + { + return new Dictionary>(base.GetFieldDeserializers()) + { + { "audioStreams", n => { AudioStreams = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInResponse.CreateFromDiscriminatorValue); } }, + { "ultraHighDefinitionVideoStream", n => { UltraHighDefinitionVideoStream = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableToOneDataStreamInResponse.CreateFromDiscriminatorValue); } }, + { "videoStream", n => { VideoStream = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToOneDataStreamInResponse.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public override void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + base.Serialize(writer); + writer.WriteObjectValue("audioStreams", AudioStreams); + writer.WriteObjectValue("ultraHighDefinitionVideoStream", UltraHighDefinitionVideoStream); + writer.WriteObjectValue("videoStream", VideoStream); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceCollectionTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceCollectionTopLevelLinks.cs new file mode 100644 index 0000000000..34acd5ed32 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceCollectionTopLevelLinks.cs @@ -0,0 +1,115 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceCollectionTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The first property + public string? First + { + get { return BackingStore?.Get("first"); } + set { BackingStore?.Set("first", value); } + } + + /// The last property + public string? Last + { + get { return BackingStore?.Get("last"); } + set { BackingStore?.Set("last", value); } + } + + /// The next property + public string? Next + { + get { return BackingStore?.Get("next"); } + set { BackingStore?.Set("next", value); } + } + + /// The prev property + public string? Prev + { + get { return BackingStore?.Get("prev"); } + set { BackingStore?.Set("prev", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceCollectionTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceCollectionTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceCollectionTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "first", n => { First = n.GetStringValue(); } }, + { "last", n => { Last = n.GetStringValue(); } }, + { "next", n => { Next = n.GetStringValue(); } }, + { "prev", n => { Prev = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("first", First); + writer.WriteStringValue("last", Last); + writer.WriteStringValue("next", Next); + writer.WriteStringValue("prev", Prev); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs new file mode 100644 index 0000000000..2ec89ef5ef --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceIdentifierCollectionTopLevelLinks.cs @@ -0,0 +1,124 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceIdentifierCollectionTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The first property + public string? First + { + get { return BackingStore?.Get("first"); } + set { BackingStore?.Set("first", value); } + } + + /// The last property + public string? Last + { + get { return BackingStore?.Get("last"); } + set { BackingStore?.Set("last", value); } + } + + /// The next property + public string? Next + { + get { return BackingStore?.Get("next"); } + set { BackingStore?.Set("next", value); } + } + + /// The prev property + public string? Prev + { + get { return BackingStore?.Get("prev"); } + set { BackingStore?.Set("prev", value); } + } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceIdentifierCollectionTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceIdentifierCollectionTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "first", n => { First = n.GetStringValue(); } }, + { "last", n => { Last = n.GetStringValue(); } }, + { "next", n => { Next = n.GetStringValue(); } }, + { "prev", n => { Prev = n.GetStringValue(); } }, + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("first", First); + writer.WriteStringValue("last", Last); + writer.WriteStringValue("next", Next); + writer.WriteStringValue("prev", Prev); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceIdentifierTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceIdentifierTopLevelLinks.cs new file mode 100644 index 0000000000..5b9950d800 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceIdentifierTopLevelLinks.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceIdentifierTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The related property + public string? Related + { + get { return BackingStore?.Get("related"); } + set { BackingStore?.Set("related", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceIdentifierTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceIdentifierTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceIdentifierTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "related", n => { Related = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("related", Related); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceInCreateRequest.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceInCreateRequest.cs new file mode 100644 index 0000000000..dae9e59575 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceInCreateRequest.cs @@ -0,0 +1,84 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInCreateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInCreateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceInCreateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "writeOnlyChannels" => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInCreateWriteOnlyChannelRequest(), + _ => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceInCreateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceInResponse.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceInResponse.cs new file mode 100644 index 0000000000..ce97d6a1c8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceInResponse.cs @@ -0,0 +1,87 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "dataStreams" => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInDataStreamResponse(), + "readOnlyChannels" => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInReadOnlyChannelResponse(), + "readOnlyResourceChannels" => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInReadOnlyResourceChannelResponse(), + "writeOnlyChannels" => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInWriteOnlyChannelResponse(), + _ => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceInResponse(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceInUpdateRequest.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceInUpdateRequest.cs new file mode 100644 index 0000000000..395a5e9419 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceInUpdateRequest.cs @@ -0,0 +1,84 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceInUpdateRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// The type property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceType? Type + { + get { return BackingStore?.Get("type"); } + set { BackingStore?.Set("type", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceInUpdateRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceInUpdateRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + var mappingValue = parseNode.GetChildNode("type")?.GetStringValue(); + return mappingValue switch + { + "writeOnlyChannels" => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInUpdateWriteOnlyChannelRequest(), + _ => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceInUpdateRequest(), + }; + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + { "type", n => { Type = n.GetEnumValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("meta", Meta); + writer.WriteEnumValue("type", Type); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceLinks.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceLinks.cs new file mode 100644 index 0000000000..857cfd5557 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceLinks.cs @@ -0,0 +1,70 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceTopLevelLinks.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceTopLevelLinks.cs new file mode 100644 index 0000000000..9ebe742c04 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceTopLevelLinks.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ResourceTopLevelLinks : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The describedby property + public string? Describedby + { + get { return BackingStore?.Get("describedby"); } + set { BackingStore?.Set("describedby", value); } + } + + /// The self property + public string? Self + { + get { return BackingStore?.Get("self"); } + set { BackingStore?.Set("self", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ResourceTopLevelLinks() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceTopLevelLinks CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceTopLevelLinks(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "describedby", n => { Describedby = n.GetStringValue(); } }, + { "self", n => { Self = n.GetStringValue(); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("describedby", Describedby); + writer.WriteStringValue("self", Self); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceType.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceType.cs new file mode 100644 index 0000000000..27d51220ab --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ResourceType.cs @@ -0,0 +1,30 @@ +// +#nullable enable +#pragma warning disable CS8625 +using System.Runtime.Serialization; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum ResourceType + #pragma warning restore CS1591 + { + [EnumMember(Value = "dataStreams")] + #pragma warning disable CS1591 + DataStreams, + #pragma warning restore CS1591 + [EnumMember(Value = "readOnlyChannels")] + #pragma warning disable CS1591 + ReadOnlyChannels, + #pragma warning restore CS1591 + [EnumMember(Value = "readOnlyResourceChannels")] + #pragma warning disable CS1591 + ReadOnlyResourceChannels, + #pragma warning restore CS1591 + [EnumMember(Value = "writeOnlyChannels")] + #pragma warning disable CS1591 + WriteOnlyChannels, + #pragma warning restore CS1591 + } +} diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/SecondaryDataStreamResponseDocument.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/SecondaryDataStreamResponseDocument.cs new file mode 100644 index 0000000000..6314c4e2e2 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/SecondaryDataStreamResponseDocument.cs @@ -0,0 +1,97 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class SecondaryDataStreamResponseDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInDataStreamResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The included property + public List? Included + { + get { return BackingStore?.Get?>("included"); } + set { BackingStore?.Set("included", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceTopLevelLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public SecondaryDataStreamResponseDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.SecondaryDataStreamResponseDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.SecondaryDataStreamResponseDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInDataStreamResponse.CreateFromDiscriminatorValue); } }, + { "included", n => { Included = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ResourceTopLevelLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteCollectionOfObjectValues("included", Included); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ToManyDataStreamInRequest.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ToManyDataStreamInRequest.cs new file mode 100644 index 0000000000..7ecfdcb19d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ToManyDataStreamInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyDataStreamInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyDataStreamInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierInRequest.CreateFromDiscriminatorValue)?.AsList(); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ToManyDataStreamInResponse.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ToManyDataStreamInResponse.cs new file mode 100644 index 0000000000..928ff49881 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ToManyDataStreamInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToManyDataStreamInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public List? Data + { + get { return BackingStore?.Get?>("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToManyDataStreamInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetCollectionOfObjectValues(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierInResponse.CreateFromDiscriminatorValue)?.AsList(); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteCollectionOfObjectValues("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ToOneDataStreamInRequest.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ToOneDataStreamInRequest.cs new file mode 100644 index 0000000000..d1528a2617 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ToOneDataStreamInRequest.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToOneDataStreamInRequest : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierInRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToOneDataStreamInRequest() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToOneDataStreamInRequest CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToOneDataStreamInRequest(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierInRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ToOneDataStreamInResponse.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ToOneDataStreamInResponse.cs new file mode 100644 index 0000000000..cb92f96da3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/ToOneDataStreamInResponse.cs @@ -0,0 +1,88 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class ToOneDataStreamInResponse : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierInResponse? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The links property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipLinks? Links + { + get { return BackingStore?.Get("links"); } + set { BackingStore?.Set("links", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public ToOneDataStreamInResponse() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToOneDataStreamInResponse CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToOneDataStreamInResponse(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierInResponse.CreateFromDiscriminatorValue); } }, + { "links", n => { Links = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.RelationshipLinks.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("links", Links); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/UpdateWriteOnlyChannelRequestDocument.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/UpdateWriteOnlyChannelRequestDocument.cs new file mode 100644 index 0000000000..2ee1033f63 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/Models/UpdateWriteOnlyChannelRequestDocument.cs @@ -0,0 +1,79 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Store; +using System.Collections.Generic; +using System.IO; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class UpdateWriteOnlyChannelRequestDocument : IBackedModel, IParsable + #pragma warning restore CS1591 + { + /// Stores model information. + public IBackingStore BackingStore { get; private set; } + + /// The data property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInUpdateWriteOnlyChannelRequest? Data + { + get { return BackingStore?.Get("data"); } + set { BackingStore?.Set("data", value); } + } + + /// The meta property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta? Meta + { + get { return BackingStore?.Get("meta"); } + set { BackingStore?.Set("meta", value); } + } + + /// + /// Instantiates a new and sets the default values. + /// + public UpdateWriteOnlyChannelRequestDocument() + { + BackingStore = BackingStoreFactorySingleton.Instance.CreateBackingStore(); + } + + /// + /// Creates a new instance of the appropriate class based on discriminator value + /// + /// A + /// The parse node to use to read the discriminator value and create the object + public static global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.UpdateWriteOnlyChannelRequestDocument CreateFromDiscriminatorValue(IParseNode parseNode) + { + _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode)); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.UpdateWriteOnlyChannelRequestDocument(); + } + + /// + /// The deserialization information for the current model + /// + /// A IDictionary<string, Action<IParseNode>> + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> + { + { "data", n => { Data = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataInUpdateWriteOnlyChannelRequest.CreateFromDiscriminatorValue); } }, + { "meta", n => { Meta = n.GetObjectValue(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.Meta.CreateFromDiscriminatorValue); } }, + }; + } + + /// + /// Serializes information the current object + /// + /// Serialization writer to use to serialize this model + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteObjectValue("data", Data); + writer.WriteObjectValue("meta", Meta); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/AudioStreams/AudioStreamsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/AudioStreams/AudioStreamsRequestBuilder.cs new file mode 100644 index 0000000000..2d07d91395 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/AudioStreams/AudioStreamsRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.AudioStreams +{ + /// + /// Builds and executes requests for operations under \readOnlyChannels\{id}\audioStreams + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AudioStreamsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public AudioStreamsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyChannels/{id}/audioStreams{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public AudioStreamsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyChannels/{id}/audioStreams{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related dataStreams of an individual readOnlyChannel's audioStreams relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related dataStreams of an individual readOnlyChannel's audioStreams relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.AudioStreams.AudioStreamsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.AudioStreams.AudioStreamsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related dataStreams of an individual readOnlyChannel's audioStreams relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AudioStreamsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AudioStreamsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/ReadOnlyChannelsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/ReadOnlyChannelsItemRequestBuilder.cs new file mode 100644 index 0000000000..a2fd224a9c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/ReadOnlyChannelsItemRequestBuilder.cs @@ -0,0 +1,156 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.AudioStreams; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.Relationships; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.UltraHighDefinitionVideoStream; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.VideoStream; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item +{ + /// + /// Builds and executes requests for operations under \readOnlyChannels\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ReadOnlyChannelsItemRequestBuilder : BaseRequestBuilder + { + /// The audioStreams property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.AudioStreams.AudioStreamsRequestBuilder AudioStreams + { + get => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.AudioStreams.AudioStreamsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The relationships property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The ultraHighDefinitionVideoStream property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.UltraHighDefinitionVideoStream.UltraHighDefinitionVideoStreamRequestBuilder UltraHighDefinitionVideoStream + { + get => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.UltraHighDefinitionVideoStream.UltraHighDefinitionVideoStreamRequestBuilder(PathParameters, RequestAdapter); + } + + /// The videoStream property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.VideoStream.VideoStreamRequestBuilder VideoStream + { + get => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.VideoStream.VideoStreamRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ReadOnlyChannelsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyChannels/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ReadOnlyChannelsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyChannels/{id}{?query*}", rawUrl) + { + } + + /// + /// Retrieves an individual readOnlyChannel by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.PrimaryReadOnlyChannelResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual readOnlyChannel by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.ReadOnlyChannelsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.ReadOnlyChannelsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual readOnlyChannel by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ReadOnlyChannelsItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ReadOnlyChannelsItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/Relationships/AudioStreams/AudioStreamsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/Relationships/AudioStreams/AudioStreamsRequestBuilder.cs new file mode 100644 index 0000000000..791f245a90 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/Relationships/AudioStreams/AudioStreamsRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.Relationships.AudioStreams +{ + /// + /// Builds and executes requests for operations under \readOnlyChannels\{id}\relationships\audioStreams + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AudioStreamsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public AudioStreamsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyChannels/{id}/relationships/audioStreams{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public AudioStreamsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyChannels/{id}/relationships/audioStreams{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related dataStream identities of an individual readOnlyChannel's audioStreams relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related dataStream identities of an individual readOnlyChannel's audioStreams relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.Relationships.AudioStreams.AudioStreamsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.Relationships.AudioStreams.AudioStreamsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related dataStream identities of an individual readOnlyChannel's audioStreams relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AudioStreamsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AudioStreamsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..984e7109db --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.Relationships.AudioStreams; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.Relationships.UltraHighDefinitionVideoStream; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.Relationships.VideoStream; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \readOnlyChannels\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The audioStreams property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.Relationships.AudioStreams.AudioStreamsRequestBuilder AudioStreams + { + get => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.Relationships.AudioStreams.AudioStreamsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The ultraHighDefinitionVideoStream property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.Relationships.UltraHighDefinitionVideoStream.UltraHighDefinitionVideoStreamRequestBuilder UltraHighDefinitionVideoStream + { + get => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.Relationships.UltraHighDefinitionVideoStream.UltraHighDefinitionVideoStreamRequestBuilder(PathParameters, RequestAdapter); + } + + /// The videoStream property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.Relationships.VideoStream.VideoStreamRequestBuilder VideoStream + { + get => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.Relationships.VideoStream.VideoStreamRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyChannels/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyChannels/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/Relationships/UltraHighDefinitionVideoStream/UltraHighDefinitionVideoStreamRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/Relationships/UltraHighDefinitionVideoStream/UltraHighDefinitionVideoStreamRequestBuilder.cs new file mode 100644 index 0000000000..6ef507aaa3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/Relationships/UltraHighDefinitionVideoStream/UltraHighDefinitionVideoStreamRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.Relationships.UltraHighDefinitionVideoStream +{ + /// + /// Builds and executes requests for operations under \readOnlyChannels\{id}\relationships\ultraHighDefinitionVideoStream + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class UltraHighDefinitionVideoStreamRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public UltraHighDefinitionVideoStreamRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyChannels/{id}/relationships/ultraHighDefinitionVideoStream{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public UltraHighDefinitionVideoStreamRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyChannels/{id}/relationships/ultraHighDefinitionVideoStream{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related dataStream identity of an individual readOnlyChannel's ultraHighDefinitionVideoStream relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableDataStreamIdentifierResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related dataStream identity of an individual readOnlyChannel's ultraHighDefinitionVideoStream relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.Relationships.UltraHighDefinitionVideoStream.UltraHighDefinitionVideoStreamRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.Relationships.UltraHighDefinitionVideoStream.UltraHighDefinitionVideoStreamRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related dataStream identity of an individual readOnlyChannel's ultraHighDefinitionVideoStream relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class UltraHighDefinitionVideoStreamRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class UltraHighDefinitionVideoStreamRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/Relationships/VideoStream/VideoStreamRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/Relationships/VideoStream/VideoStreamRequestBuilder.cs new file mode 100644 index 0000000000..86c101ef24 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/Relationships/VideoStream/VideoStreamRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.Relationships.VideoStream +{ + /// + /// Builds and executes requests for operations under \readOnlyChannels\{id}\relationships\videoStream + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class VideoStreamRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public VideoStreamRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyChannels/{id}/relationships/videoStream{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public VideoStreamRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyChannels/{id}/relationships/videoStream{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related dataStream identity of an individual readOnlyChannel's videoStream relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related dataStream identity of an individual readOnlyChannel's videoStream relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.Relationships.VideoStream.VideoStreamRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.Relationships.VideoStream.VideoStreamRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related dataStream identity of an individual readOnlyChannel's videoStream relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class VideoStreamRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class VideoStreamRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/UltraHighDefinitionVideoStream/UltraHighDefinitionVideoStreamRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/UltraHighDefinitionVideoStream/UltraHighDefinitionVideoStreamRequestBuilder.cs new file mode 100644 index 0000000000..919369dde1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/UltraHighDefinitionVideoStream/UltraHighDefinitionVideoStreamRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.UltraHighDefinitionVideoStream +{ + /// + /// Builds and executes requests for operations under \readOnlyChannels\{id}\ultraHighDefinitionVideoStream + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class UltraHighDefinitionVideoStreamRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public UltraHighDefinitionVideoStreamRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyChannels/{id}/ultraHighDefinitionVideoStream{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public UltraHighDefinitionVideoStreamRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyChannels/{id}/ultraHighDefinitionVideoStream{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related dataStream of an individual readOnlyChannel's ultraHighDefinitionVideoStream relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableSecondaryDataStreamResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related dataStream of an individual readOnlyChannel's ultraHighDefinitionVideoStream relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.UltraHighDefinitionVideoStream.UltraHighDefinitionVideoStreamRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.UltraHighDefinitionVideoStream.UltraHighDefinitionVideoStreamRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related dataStream of an individual readOnlyChannel's ultraHighDefinitionVideoStream relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class UltraHighDefinitionVideoStreamRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class UltraHighDefinitionVideoStreamRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/VideoStream/VideoStreamRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/VideoStream/VideoStreamRequestBuilder.cs new file mode 100644 index 0000000000..75950fccaa --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/Item/VideoStream/VideoStreamRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.VideoStream +{ + /// + /// Builds and executes requests for operations under \readOnlyChannels\{id}\videoStream + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class VideoStreamRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public VideoStreamRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyChannels/{id}/videoStream{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public VideoStreamRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyChannels/{id}/videoStream{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related dataStream of an individual readOnlyChannel's videoStream relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.SecondaryDataStreamResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related dataStream of an individual readOnlyChannel's videoStream relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.VideoStream.VideoStreamRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.VideoStream.VideoStreamRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related dataStream of an individual readOnlyChannel's videoStream relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class VideoStreamRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class VideoStreamRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/ReadOnlyChannelsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/ReadOnlyChannelsRequestBuilder.cs new file mode 100644 index 0000000000..33f9ab8a74 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyChannels/ReadOnlyChannelsRequestBuilder.cs @@ -0,0 +1,140 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels +{ + /// + /// Builds and executes requests for operations under \readOnlyChannels + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ReadOnlyChannelsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.readOnlyChannels.item collection + /// The identifier of the readOnlyChannel to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.ReadOnlyChannelsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.Item.ReadOnlyChannelsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ReadOnlyChannelsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyChannels{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ReadOnlyChannelsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyChannels{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of readOnlyChannels. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ReadOnlyChannelCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of readOnlyChannels. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.ReadOnlyChannelsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.ReadOnlyChannelsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of readOnlyChannels. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ReadOnlyChannelsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ReadOnlyChannelsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyResourceChannels/Item/AudioStreams/AudioStreamsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyResourceChannels/Item/AudioStreams/AudioStreamsRequestBuilder.cs new file mode 100644 index 0000000000..53cac43c79 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyResourceChannels/Item/AudioStreams/AudioStreamsRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item.AudioStreams +{ + /// + /// Builds and executes requests for operations under \readOnlyResourceChannels\{id}\audioStreams + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AudioStreamsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public AudioStreamsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyResourceChannels/{id}/audioStreams{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public AudioStreamsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyResourceChannels/{id}/audioStreams{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related dataStreams of an individual readOnlyResourceChannel's audioStreams relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related dataStreams of an individual readOnlyResourceChannel's audioStreams relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item.AudioStreams.AudioStreamsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item.AudioStreams.AudioStreamsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related dataStreams of an individual readOnlyResourceChannel's audioStreams relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AudioStreamsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AudioStreamsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyResourceChannels/Item/ReadOnlyResourceChannelsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyResourceChannels/Item/ReadOnlyResourceChannelsItemRequestBuilder.cs new file mode 100644 index 0000000000..56dc09df25 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyResourceChannels/Item/ReadOnlyResourceChannelsItemRequestBuilder.cs @@ -0,0 +1,149 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item.AudioStreams; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item.UltraHighDefinitionVideoStream; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item.VideoStream; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item +{ + /// + /// Builds and executes requests for operations under \readOnlyResourceChannels\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ReadOnlyResourceChannelsItemRequestBuilder : BaseRequestBuilder + { + /// The audioStreams property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item.AudioStreams.AudioStreamsRequestBuilder AudioStreams + { + get => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item.AudioStreams.AudioStreamsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The ultraHighDefinitionVideoStream property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item.UltraHighDefinitionVideoStream.UltraHighDefinitionVideoStreamRequestBuilder UltraHighDefinitionVideoStream + { + get => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item.UltraHighDefinitionVideoStream.UltraHighDefinitionVideoStreamRequestBuilder(PathParameters, RequestAdapter); + } + + /// The videoStream property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item.VideoStream.VideoStreamRequestBuilder VideoStream + { + get => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item.VideoStream.VideoStreamRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ReadOnlyResourceChannelsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyResourceChannels/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ReadOnlyResourceChannelsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyResourceChannels/{id}{?query*}", rawUrl) + { + } + + /// + /// Retrieves an individual readOnlyResourceChannel by its identifier. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.PrimaryReadOnlyResourceChannelResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves an individual readOnlyResourceChannel by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item.ReadOnlyResourceChannelsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item.ReadOnlyResourceChannelsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves an individual readOnlyResourceChannel by its identifier. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ReadOnlyResourceChannelsItemRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ReadOnlyResourceChannelsItemRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyResourceChannels/Item/UltraHighDefinitionVideoStream/UltraHighDefinitionVideoStreamRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyResourceChannels/Item/UltraHighDefinitionVideoStream/UltraHighDefinitionVideoStreamRequestBuilder.cs new file mode 100644 index 0000000000..69411ac0e8 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyResourceChannels/Item/UltraHighDefinitionVideoStream/UltraHighDefinitionVideoStreamRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item.UltraHighDefinitionVideoStream +{ + /// + /// Builds and executes requests for operations under \readOnlyResourceChannels\{id}\ultraHighDefinitionVideoStream + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class UltraHighDefinitionVideoStreamRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public UltraHighDefinitionVideoStreamRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyResourceChannels/{id}/ultraHighDefinitionVideoStream{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public UltraHighDefinitionVideoStreamRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyResourceChannels/{id}/ultraHighDefinitionVideoStream{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related dataStream of an individual readOnlyResourceChannel's ultraHighDefinitionVideoStream relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableSecondaryDataStreamResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related dataStream of an individual readOnlyResourceChannel's ultraHighDefinitionVideoStream relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item.UltraHighDefinitionVideoStream.UltraHighDefinitionVideoStreamRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item.UltraHighDefinitionVideoStream.UltraHighDefinitionVideoStreamRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related dataStream of an individual readOnlyResourceChannel's ultraHighDefinitionVideoStream relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class UltraHighDefinitionVideoStreamRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class UltraHighDefinitionVideoStreamRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyResourceChannels/Item/VideoStream/VideoStreamRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyResourceChannels/Item/VideoStream/VideoStreamRequestBuilder.cs new file mode 100644 index 0000000000..2b199a5fed --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyResourceChannels/Item/VideoStream/VideoStreamRequestBuilder.cs @@ -0,0 +1,128 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item.VideoStream +{ + /// + /// Builds and executes requests for operations under \readOnlyResourceChannels\{id}\videoStream + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class VideoStreamRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public VideoStreamRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyResourceChannels/{id}/videoStream{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public VideoStreamRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyResourceChannels/{id}/videoStream{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related dataStream of an individual readOnlyResourceChannel's videoStream relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.SecondaryDataStreamResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related dataStream of an individual readOnlyResourceChannel's videoStream relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item.VideoStream.VideoStreamRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item.VideoStream.VideoStreamRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related dataStream of an individual readOnlyResourceChannel's videoStream relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class VideoStreamRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class VideoStreamRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyResourceChannels/ReadOnlyResourceChannelsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyResourceChannels/ReadOnlyResourceChannelsRequestBuilder.cs new file mode 100644 index 0000000000..5ee482011c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/ReadOnlyResourceChannels/ReadOnlyResourceChannelsRequestBuilder.cs @@ -0,0 +1,140 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels +{ + /// + /// Builds and executes requests for operations under \readOnlyResourceChannels + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ReadOnlyResourceChannelsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.readOnlyResourceChannels.item collection + /// The identifier of the readOnlyResourceChannel to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item.ReadOnlyResourceChannelsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.Item.ReadOnlyResourceChannelsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public ReadOnlyResourceChannelsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyResourceChannels{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public ReadOnlyResourceChannelsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/readOnlyResourceChannels{?query*}", rawUrl) + { + } + + /// + /// Retrieves a collection of readOnlyResourceChannels. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ReadOnlyResourceChannelCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves a collection of readOnlyResourceChannels. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.ReadOnlyResourceChannelsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.ReadOnlyResourceChannelsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves a collection of readOnlyResourceChannels. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ReadOnlyResourceChannelsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class ReadOnlyResourceChannelsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/RelationshipChannels/Item/RelationshipChannelsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/RelationshipChannels/Item/RelationshipChannelsItemRequestBuilder.cs new file mode 100644 index 0000000000..d4e397d3ac --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/RelationshipChannels/Item/RelationshipChannelsItemRequestBuilder.cs @@ -0,0 +1,45 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.Relationships; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item +{ + /// + /// Builds and executes requests for operations under \relationshipChannels\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipChannelsItemRequestBuilder : BaseRequestBuilder + { + /// The relationships property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipChannelsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/relationshipChannels/{id}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipChannelsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/relationshipChannels/{id}", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/RelationshipChannels/Item/Relationships/AudioStreams/AudioStreamsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/RelationshipChannels/Item/Relationships/AudioStreams/AudioStreamsRequestBuilder.cs new file mode 100644 index 0000000000..cfc146b291 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/RelationshipChannels/Item/Relationships/AudioStreams/AudioStreamsRequestBuilder.cs @@ -0,0 +1,248 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.Relationships.AudioStreams +{ + /// + /// Builds and executes requests for operations under \relationshipChannels\{id}\relationships\audioStreams + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AudioStreamsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public AudioStreamsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/relationshipChannels/{id}/relationships/audioStreams{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public AudioStreamsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/relationshipChannels/{id}/relationships/audioStreams{?query*}", rawUrl) + { + } + + /// + /// Removes existing dataStreams from the audioStreams relationship of an individual relationshipChannel. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task DeleteAsync(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToDeleteRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related dataStream identities of an individual relationshipChannel's audioStreams relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns existing dataStreams to the audioStreams relationship of an individual relationshipChannel. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Adds existing dataStreams to the audioStreams relationship of an individual relationshipChannel. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Removes existing dataStreams from the audioStreams relationship of an individual relationshipChannel. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Retrieves the related dataStream identities of an individual relationshipChannel's audioStreams relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns existing dataStreams to the audioStreams relationship of an individual relationshipChannel. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Adds existing dataStreams to the audioStreams relationship of an individual relationshipChannel. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.Relationships.AudioStreams.AudioStreamsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.Relationships.AudioStreams.AudioStreamsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related dataStream identities of an individual relationshipChannel's audioStreams relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AudioStreamsRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AudioStreamsRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/RelationshipChannels/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/RelationshipChannels/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..cad98da8bf --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/RelationshipChannels/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.Relationships.AudioStreams; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.Relationships.UltraHighDefinitionVideoStream; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.Relationships.VideoStream; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \relationshipChannels\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The audioStreams property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.Relationships.AudioStreams.AudioStreamsRequestBuilder AudioStreams + { + get => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.Relationships.AudioStreams.AudioStreamsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The ultraHighDefinitionVideoStream property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.Relationships.UltraHighDefinitionVideoStream.UltraHighDefinitionVideoStreamRequestBuilder UltraHighDefinitionVideoStream + { + get => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.Relationships.UltraHighDefinitionVideoStream.UltraHighDefinitionVideoStreamRequestBuilder(PathParameters, RequestAdapter); + } + + /// The videoStream property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.Relationships.VideoStream.VideoStreamRequestBuilder VideoStream + { + get => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.Relationships.VideoStream.VideoStreamRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/relationshipChannels/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/relationshipChannels/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/RelationshipChannels/Item/Relationships/UltraHighDefinitionVideoStream/UltraHighDefinitionVideoStreamRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/RelationshipChannels/Item/Relationships/UltraHighDefinitionVideoStream/UltraHighDefinitionVideoStreamRequestBuilder.cs new file mode 100644 index 0000000000..6f7c00a048 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/RelationshipChannels/Item/Relationships/UltraHighDefinitionVideoStream/UltraHighDefinitionVideoStreamRequestBuilder.cs @@ -0,0 +1,168 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.Relationships.UltraHighDefinitionVideoStream +{ + /// + /// Builds and executes requests for operations under \relationshipChannels\{id}\relationships\ultraHighDefinitionVideoStream + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class UltraHighDefinitionVideoStreamRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public UltraHighDefinitionVideoStreamRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/relationshipChannels/{id}/relationships/ultraHighDefinitionVideoStream{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public UltraHighDefinitionVideoStreamRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/relationshipChannels/{id}/relationships/ultraHighDefinitionVideoStream{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related dataStream identity of an individual relationshipChannel's ultraHighDefinitionVideoStream relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableDataStreamIdentifierResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Clears or assigns an existing dataStream to the ultraHighDefinitionVideoStream relationship of an individual relationshipChannel. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableToOneDataStreamInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related dataStream identity of an individual relationshipChannel's ultraHighDefinitionVideoStream relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Clears or assigns an existing dataStream to the ultraHighDefinitionVideoStream relationship of an individual relationshipChannel. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableToOneDataStreamInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.Relationships.UltraHighDefinitionVideoStream.UltraHighDefinitionVideoStreamRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.Relationships.UltraHighDefinitionVideoStream.UltraHighDefinitionVideoStreamRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related dataStream identity of an individual relationshipChannel's ultraHighDefinitionVideoStream relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class UltraHighDefinitionVideoStreamRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class UltraHighDefinitionVideoStreamRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/RelationshipChannels/Item/Relationships/VideoStream/VideoStreamRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/RelationshipChannels/Item/Relationships/VideoStream/VideoStreamRequestBuilder.cs new file mode 100644 index 0000000000..56f8d6974c --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/RelationshipChannels/Item/Relationships/VideoStream/VideoStreamRequestBuilder.cs @@ -0,0 +1,168 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.Relationships.VideoStream +{ + /// + /// Builds and executes requests for operations under \relationshipChannels\{id}\relationships\videoStream + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class VideoStreamRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public VideoStreamRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/relationshipChannels/{id}/relationships/videoStream{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public VideoStreamRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/relationshipChannels/{id}/relationships/videoStream{?query*}", rawUrl) + { + } + + /// + /// Retrieves the related dataStream identity of an individual relationshipChannel's videoStream relationship. + /// + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToGetRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.DataStreamIdentifierResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + public async Task HeadAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToHeadRequestInformation(requestConfiguration); + await RequestAdapter.SendNoContentAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns an existing dataStream to the videoStream relationship of an individual relationshipChannel. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToOneDataStreamInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Retrieves the related dataStream identity of an individual relationshipChannel's videoStream relationship. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToHeadRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.HEAD, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + + /// + /// Assigns an existing dataStream to the videoStream relationship of an individual relationshipChannel. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToOneDataStreamInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.Relationships.VideoStream.VideoStreamRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.Relationships.VideoStream.VideoStreamRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Retrieves the related dataStream identity of an individual relationshipChannel's videoStream relationship. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class VideoStreamRequestBuilderGetQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + + /// + /// Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class VideoStreamRequestBuilderHeadQueryParameters + { + /// For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/RelationshipChannels/RelationshipChannelsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/RelationshipChannels/RelationshipChannelsRequestBuilder.cs new file mode 100644 index 0000000000..fb78208eee --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/RelationshipChannels/RelationshipChannelsRequestBuilder.cs @@ -0,0 +1,52 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels +{ + /// + /// Builds and executes requests for operations under \relationshipChannels + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipChannelsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.relationshipChannels.item collection + /// The identifier of the relationshipChannel whose related dataStream identities to retrieve. + /// A + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.RelationshipChannelsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.Item.RelationshipChannelsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipChannelsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/relationshipChannels", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipChannelsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/relationshipChannels", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/RestrictedControllersClient.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/RestrictedControllersClient.cs new file mode 100644 index 0000000000..3ae5195a54 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/RestrictedControllersClient.cs @@ -0,0 +1,82 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Store; +using Microsoft.Kiota.Abstractions; +using Microsoft.Kiota.Serialization.Form; +using Microsoft.Kiota.Serialization.Json; +using Microsoft.Kiota.Serialization.Multipart; +using Microsoft.Kiota.Serialization.Text; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.DataStreams; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode +{ + /// + /// The main entry point of the SDK, exposes the configuration and the fluent API. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RestrictedControllersClient : BaseRequestBuilder + { + /// The dataStreams property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.DataStreams.DataStreamsRequestBuilder DataStreams + { + get => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.DataStreams.DataStreamsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The readOnlyChannels property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.ReadOnlyChannelsRequestBuilder ReadOnlyChannels + { + get => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyChannels.ReadOnlyChannelsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The readOnlyResourceChannels property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.ReadOnlyResourceChannelsRequestBuilder ReadOnlyResourceChannels + { + get => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.ReadOnlyResourceChannels.ReadOnlyResourceChannelsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The relationshipChannels property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.RelationshipChannelsRequestBuilder RelationshipChannels + { + get => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.RelationshipChannels.RelationshipChannelsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The writeOnlyChannels property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.WriteOnlyChannelsRequestBuilder WriteOnlyChannels + { + get => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.WriteOnlyChannelsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The backing store to use for the models. + /// The request adapter to use to execute the requests. + public RestrictedControllersClient(IRequestAdapter requestAdapter, IBackingStoreFactory backingStore = default) : base(requestAdapter, "{+baseurl}", new Dictionary()) + { + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultSerializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + ApiClientBuilder.RegisterDefaultDeserializer(); + if (string.IsNullOrEmpty(RequestAdapter.BaseUrl)) + { + RequestAdapter.BaseUrl = "http://localhost"; + } + PathParameters.TryAdd("baseurl", RequestAdapter.BaseUrl); + RequestAdapter.EnableBackingStore(backingStore); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/WriteOnlyChannels/Item/Relationships/AudioStreams/AudioStreamsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/WriteOnlyChannels/Item/Relationships/AudioStreams/AudioStreamsRequestBuilder.cs new file mode 100644 index 0000000000..532ecb788a --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/WriteOnlyChannels/Item/Relationships/AudioStreams/AudioStreamsRequestBuilder.cs @@ -0,0 +1,171 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.Relationships.AudioStreams +{ + /// + /// Builds and executes requests for operations under \writeOnlyChannels\{id}\relationships\audioStreams + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class AudioStreamsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public AudioStreamsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/writeOnlyChannels/{id}/relationships/audioStreams", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public AudioStreamsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/writeOnlyChannels/{id}/relationships/audioStreams", rawUrl) + { + } + + /// + /// Removes existing dataStreams from the audioStreams relationship of an individual writeOnlyChannel. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task DeleteAsync(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToDeleteRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns existing dataStreams to the audioStreams relationship of an individual writeOnlyChannel. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Adds existing dataStreams to the audioStreams relationship of an individual writeOnlyChannel. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Removes existing dataStreams from the audioStreams relationship of an individual writeOnlyChannel. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Assigns existing dataStreams to the audioStreams relationship of an individual writeOnlyChannel. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Adds existing dataStreams to the audioStreams relationship of an individual writeOnlyChannel. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToManyDataStreamInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.Relationships.AudioStreams.AudioStreamsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.Relationships.AudioStreams.AudioStreamsRequestBuilder(rawUrl, RequestAdapter); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/WriteOnlyChannels/Item/Relationships/RelationshipsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/WriteOnlyChannels/Item/Relationships/RelationshipsRequestBuilder.cs new file mode 100644 index 0000000000..c5b04aaa43 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/WriteOnlyChannels/Item/Relationships/RelationshipsRequestBuilder.cs @@ -0,0 +1,59 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.Relationships.AudioStreams; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.Relationships.UltraHighDefinitionVideoStream; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.Relationships.VideoStream; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.Relationships +{ + /// + /// Builds and executes requests for operations under \writeOnlyChannels\{id}\relationships + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class RelationshipsRequestBuilder : BaseRequestBuilder + { + /// The audioStreams property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.Relationships.AudioStreams.AudioStreamsRequestBuilder AudioStreams + { + get => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.Relationships.AudioStreams.AudioStreamsRequestBuilder(PathParameters, RequestAdapter); + } + + /// The ultraHighDefinitionVideoStream property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.Relationships.UltraHighDefinitionVideoStream.UltraHighDefinitionVideoStreamRequestBuilder UltraHighDefinitionVideoStream + { + get => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.Relationships.UltraHighDefinitionVideoStream.UltraHighDefinitionVideoStreamRequestBuilder(PathParameters, RequestAdapter); + } + + /// The videoStream property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.Relationships.VideoStream.VideoStreamRequestBuilder VideoStream + { + get => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.Relationships.VideoStream.VideoStreamRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/writeOnlyChannels/{id}/relationships", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public RelationshipsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/writeOnlyChannels/{id}/relationships", rawUrl) + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/WriteOnlyChannels/Item/Relationships/UltraHighDefinitionVideoStream/UltraHighDefinitionVideoStreamRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/WriteOnlyChannels/Item/Relationships/UltraHighDefinitionVideoStream/UltraHighDefinitionVideoStreamRequestBuilder.cs new file mode 100644 index 0000000000..ad24e4691e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/WriteOnlyChannels/Item/Relationships/UltraHighDefinitionVideoStream/UltraHighDefinitionVideoStreamRequestBuilder.cs @@ -0,0 +1,91 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.Relationships.UltraHighDefinitionVideoStream +{ + /// + /// Builds and executes requests for operations under \writeOnlyChannels\{id}\relationships\ultraHighDefinitionVideoStream + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class UltraHighDefinitionVideoStreamRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public UltraHighDefinitionVideoStreamRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/writeOnlyChannels/{id}/relationships/ultraHighDefinitionVideoStream", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public UltraHighDefinitionVideoStreamRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/writeOnlyChannels/{id}/relationships/ultraHighDefinitionVideoStream", rawUrl) + { + } + + /// + /// Clears or assigns an existing dataStream to the ultraHighDefinitionVideoStream relationship of an individual writeOnlyChannel. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableToOneDataStreamInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Clears or assigns an existing dataStream to the ultraHighDefinitionVideoStream relationship of an individual writeOnlyChannel. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.NullableToOneDataStreamInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.Relationships.UltraHighDefinitionVideoStream.UltraHighDefinitionVideoStreamRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.Relationships.UltraHighDefinitionVideoStream.UltraHighDefinitionVideoStreamRequestBuilder(rawUrl, RequestAdapter); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/WriteOnlyChannels/Item/Relationships/VideoStream/VideoStreamRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/WriteOnlyChannels/Item/Relationships/VideoStream/VideoStreamRequestBuilder.cs new file mode 100644 index 0000000000..da71988d09 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/WriteOnlyChannels/Item/Relationships/VideoStream/VideoStreamRequestBuilder.cs @@ -0,0 +1,91 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.Relationships.VideoStream +{ + /// + /// Builds and executes requests for operations under \writeOnlyChannels\{id}\relationships\videoStream + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class VideoStreamRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public VideoStreamRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/writeOnlyChannels/{id}/relationships/videoStream", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public VideoStreamRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/writeOnlyChannels/{id}/relationships/videoStream", rawUrl) + { + } + + /// + /// Assigns an existing dataStream to the videoStream relationship of an individual writeOnlyChannel. + /// + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToOneDataStreamInRequest body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Assigns an existing dataStream to the videoStream relationship of an individual writeOnlyChannel. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ToOneDataStreamInRequest body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.Relationships.VideoStream.VideoStreamRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.Relationships.VideoStream.VideoStreamRequestBuilder(rawUrl, RequestAdapter); + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/WriteOnlyChannels/Item/WriteOnlyChannelsItemRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/WriteOnlyChannels/Item/WriteOnlyChannelsItemRequestBuilder.cs new file mode 100644 index 0000000000..2e324e4622 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/WriteOnlyChannels/Item/WriteOnlyChannelsItemRequestBuilder.cs @@ -0,0 +1,139 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.Relationships; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item +{ + /// + /// Builds and executes requests for operations under \writeOnlyChannels\{id} + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class WriteOnlyChannelsItemRequestBuilder : BaseRequestBuilder + { + /// The relationships property + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.Relationships.RelationshipsRequestBuilder Relationships + { + get => new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.Relationships.RelationshipsRequestBuilder(PathParameters, RequestAdapter); + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public WriteOnlyChannelsItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/writeOnlyChannels/{id}{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public WriteOnlyChannelsItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/writeOnlyChannels/{id}{?query*}", rawUrl) + { + } + + /// + /// Deletes an existing writeOnlyChannel by its identifier. + /// + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 404 status code + public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + var requestInfo = ToDeleteRequestInformation(requestConfiguration); + var errorMapping = new Dictionary> + { + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Updates an existing writeOnlyChannel. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PatchAsync(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.UpdateWriteOnlyChannelRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPatchRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.PrimaryWriteOnlyChannelResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Deletes an existing writeOnlyChannel by its identifier. + /// + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default) + { + var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + return requestInfo; + } + + /// + /// Updates an existing writeOnlyChannel. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPatchRequestInformation(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.UpdateWriteOnlyChannelRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.WriteOnlyChannelsItemRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.WriteOnlyChannelsItemRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Updates an existing writeOnlyChannel. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class WriteOnlyChannelsItemRequestBuilderPatchQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/WriteOnlyChannels/WriteOnlyChannelsRequestBuilder.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/WriteOnlyChannels/WriteOnlyChannelsRequestBuilder.cs new file mode 100644 index 0000000000..b50d4ec156 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/WriteOnlyChannels/WriteOnlyChannelsRequestBuilder.cs @@ -0,0 +1,119 @@ +// +#nullable enable +#pragma warning disable CS8625 +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels +{ + /// + /// Builds and executes requests for operations under \writeOnlyChannels + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class WriteOnlyChannelsRequestBuilder : BaseRequestBuilder + { + /// Gets an item from the OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.writeOnlyChannels.item collection + /// The identifier of the writeOnlyChannel to update. + /// A + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.WriteOnlyChannelsItemRequestBuilder this[string position] + { + get + { + var urlTplParams = new Dictionary(PathParameters); + urlTplParams.Add("id", position); + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.Item.WriteOnlyChannelsItemRequestBuilder(urlTplParams, RequestAdapter); + } + } + + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public WriteOnlyChannelsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/writeOnlyChannels{?query*}", pathParameters) + { + } + + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public WriteOnlyChannelsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/writeOnlyChannels{?query*}", rawUrl) + { + } + + /// + /// Creates a new writeOnlyChannel. + /// + /// A + /// The request body + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. + /// When receiving a 400 status code + /// When receiving a 403 status code + /// When receiving a 404 status code + /// When receiving a 409 status code + /// When receiving a 422 status code + public async Task PostAsync(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.CreateWriteOnlyChannelRequestDocument body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = ToPostRequestInformation(body, requestConfiguration); + var errorMapping = new Dictionary> + { + { "400", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "403", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "404", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "409", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + { "422", global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.ErrorResponseDocument.CreateFromDiscriminatorValue }, + }; + return await RequestAdapter.SendAsync(requestInfo, global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.PrimaryWriteOnlyChannelResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a new writeOnlyChannel. + /// + /// A + /// The request body + /// Configuration for the request such as headers, query parameters, and middleware options. + public RequestInformation ToPostRequestInformation(global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models.CreateWriteOnlyChannelRequestDocument body, Action>? requestConfiguration = default) + { + _ = body ?? throw new ArgumentNullException(nameof(body)); + var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json;ext=openapi"); + requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json;ext=openapi", body); + return requestInfo; + } + + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.WriteOnlyChannelsRequestBuilder WithUrl(string rawUrl) + { + return new global::OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.WriteOnlyChannels.WriteOnlyChannelsRequestBuilder(rawUrl, RequestAdapter); + } + + /// + /// Creates a new writeOnlyChannel. + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class WriteOnlyChannelsRequestBuilderPostQueryParameters + { + /// For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters. + [QueryParameter("query")] + public string? Query { get; set; } + } + } +} +#pragma warning restore CS0618 diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/UpdateRelationshipTests.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/UpdateRelationshipTests.cs new file mode 100644 index 0000000000..7be939449b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/UpdateRelationshipTests.cs @@ -0,0 +1,406 @@ +using System.Net; +using FluentAssertions; +using Microsoft.EntityFrameworkCore; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.RestrictedControllers; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.RestrictedControllers; + +public sealed class UpdateRelationshipTests : IClassFixture, RestrictionDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, RestrictionDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly RestrictionFakers _fakers = new(); + + public UpdateRelationshipTests(IntegrationTestContext, RestrictionDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseController(); + } + + [Fact] + public async Task Can_replace_ToOne_relationship() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + existingChannel.UltraHighDefinitionVideoStream = _fakers.DataStream.GenerateOne(); + + DataStream existingVideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + dbContext.DataStreams.Add(existingVideoStream); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + var requestBody = new NullableToOneDataStreamInRequest + { + Data = new DataStreamIdentifierInRequest + { + Type = ResourceType.DataStreams, + Id = existingVideoStream.StringId! + } + }; + + // Act + await apiClient.WriteOnlyChannels[existingChannel.StringId!].Relationships.UltraHighDefinitionVideoStream.PatchAsync(requestBody); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + // @formatter:wrap_chained_method_calls chop_always + // @formatter:keep_existing_linebreaks true + + WriteOnlyChannel channelInDatabase = await dbContext.WriteOnlyChannels + .Include(channel => channel.UltraHighDefinitionVideoStream) + .FirstWithIdAsync(existingChannel.Id); + + // @formatter:keep_existing_linebreaks restore + // @formatter:wrap_chained_method_calls restore + + channelInDatabase.UltraHighDefinitionVideoStream.Should().NotBeNull(); + channelInDatabase.UltraHighDefinitionVideoStream.Id.Should().Be(existingVideoStream.Id); + }); + } + + [Fact] + public async Task Can_clear_ToOne_relationship() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + existingChannel.UltraHighDefinitionVideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + var requestBody = new NullableToOneDataStreamInRequest + { + Data = null + }; + + // Act + await apiClient.WriteOnlyChannels[existingChannel.StringId!].Relationships.UltraHighDefinitionVideoStream.PatchAsync(requestBody); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + // @formatter:wrap_chained_method_calls chop_always + // @formatter:keep_existing_linebreaks true + + WriteOnlyChannel channelInDatabase = await dbContext.WriteOnlyChannels + .Include(channel => channel.UltraHighDefinitionVideoStream) + .FirstWithIdAsync(existingChannel.Id); + + // @formatter:keep_existing_linebreaks restore + // @formatter:wrap_chained_method_calls restore + + channelInDatabase.UltraHighDefinitionVideoStream.Should().BeNull(); + }); + } + + [Fact] + public async Task Can_replace_ToMany_relationship() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + existingChannel.AudioStreams = _fakers.DataStream.GenerateSet(2); + + DataStream existingAudioStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + dbContext.DataStreams.Add(existingAudioStream); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + var requestBody = new ToManyDataStreamInRequest + { + Data = + [ + new DataStreamIdentifierInRequest + { + Type = ResourceType.DataStreams, + Id = existingAudioStream.StringId! + } + ] + }; + + // Act + await apiClient.WriteOnlyChannels[existingChannel.StringId!].Relationships.AudioStreams.PatchAsync(requestBody); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + // @formatter:wrap_chained_method_calls chop_always + // @formatter:keep_existing_linebreaks true + + WriteOnlyChannel channelInDatabase = await dbContext.WriteOnlyChannels + .Include(channel => channel.AudioStreams) + .FirstWithIdAsync(existingChannel.Id); + + // @formatter:keep_existing_linebreaks restore + // @formatter:wrap_chained_method_calls restore + + channelInDatabase.AudioStreams.Should().HaveCount(1); + channelInDatabase.AudioStreams.ElementAt(0).Id.Should().Be(existingAudioStream.Id); + }); + } + + [Fact] + public async Task Can_clear_ToMany_relationship() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + existingChannel.AudioStreams = _fakers.DataStream.GenerateSet(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + var requestBody = new ToManyDataStreamInRequest + { + Data = [] + }; + + // Act + await apiClient.WriteOnlyChannels[existingChannel.StringId!].Relationships.AudioStreams.PatchAsync(requestBody); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + // @formatter:wrap_chained_method_calls chop_always + // @formatter:keep_existing_linebreaks true + + WriteOnlyChannel channelInDatabase = await dbContext.WriteOnlyChannels + .Include(channel => channel.AudioStreams) + .FirstWithIdAsync(existingChannel.Id); + + // @formatter:keep_existing_linebreaks restore + // @formatter:wrap_chained_method_calls restore + + channelInDatabase.AudioStreams.Should().BeEmpty(); + }); + } + + [Fact] + public async Task Can_add_to_ToMany_relationship() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + existingChannel.AudioStreams = _fakers.DataStream.GenerateSet(1); + + DataStream existingAudioStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + dbContext.DataStreams.Add(existingAudioStream); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + var requestBody = new ToManyDataStreamInRequest + { + Data = + [ + new DataStreamIdentifierInRequest + { + Type = ResourceType.DataStreams, + Id = existingAudioStream.StringId! + } + ] + }; + + // Act + await apiClient.WriteOnlyChannels[existingChannel.StringId!].Relationships.AudioStreams.PostAsync(requestBody); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + // @formatter:wrap_chained_method_calls chop_always + // @formatter:keep_existing_linebreaks true + + WriteOnlyChannel channelInDatabase = await dbContext.WriteOnlyChannels + .Include(channel => channel.AudioStreams) + .FirstWithIdAsync(existingChannel.Id); + + // @formatter:keep_existing_linebreaks restore + // @formatter:wrap_chained_method_calls restore + + channelInDatabase.AudioStreams.Should().HaveCount(2); + channelInDatabase.AudioStreams.Should().ContainSingle(stream => stream.Id == existingChannel.AudioStreams.ElementAt(0).Id); + channelInDatabase.AudioStreams.Should().ContainSingle(stream => stream.Id == existingAudioStream.Id); + }); + } + + [Fact] + public async Task Can_remove_from_ToMany_relationship() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + existingChannel.AudioStreams = _fakers.DataStream.GenerateSet(3); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + var requestBody = new ToManyDataStreamInRequest + { + Data = + [ + new DataStreamIdentifierInRequest + { + Type = ResourceType.DataStreams, + Id = existingChannel.AudioStreams.ElementAt(0).StringId! + }, + new DataStreamIdentifierInRequest + { + Type = ResourceType.DataStreams, + Id = existingChannel.AudioStreams.ElementAt(1).StringId! + } + ] + }; + + // Act + await apiClient.WriteOnlyChannels[existingChannel.StringId!].Relationships.AudioStreams.DeleteAsync(requestBody); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + // @formatter:wrap_chained_method_calls chop_always + // @formatter:keep_existing_linebreaks true + + WriteOnlyChannel channelInDatabase = await dbContext.WriteOnlyChannels + .Include(channel => channel.AudioStreams) + .FirstWithIdAsync(existingChannel.Id); + + // @formatter:keep_existing_linebreaks restore + // @formatter:wrap_chained_method_calls restore + + channelInDatabase.AudioStreams.Should().HaveCount(1); + channelInDatabase.AudioStreams.ElementAt(0).Id.Should().Be(existingChannel.AudioStreams.ElementAt(2).Id); + }); + } + + [Fact] + public async Task Cannot_update_relationship_for_missing_request_body() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + NullableToOneDataStreamInRequest requestBody = null!; + + // Act + Func action = async () => + await apiClient.WriteOnlyChannels[existingChannel.StringId!].Relationships.UltraHighDefinitionVideoStream.PatchAsync(requestBody); + + // Assert + await action.Should().ThrowExactlyAsync().WithParameterName("body"); + } + + [Fact] + public async Task Cannot_update_relationship_with_unknown_relationship_IDs() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + await dbContext.SaveChangesAsync(); + }); + + string unknownAudioStreamId1 = Unknown.StringId.For(); + string unknownAudioStreamId2 = Unknown.StringId.AltFor(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + var requestBody = new ToManyDataStreamInRequest + { + Data = + [ + new DataStreamIdentifierInRequest + { + Type = ResourceType.DataStreams, + Id = unknownAudioStreamId1 + }, + new DataStreamIdentifierInRequest + { + Type = ResourceType.DataStreams, + Id = unknownAudioStreamId2 + } + ] + }; + + // Act + Func action = async () => await apiClient.WriteOnlyChannels[existingChannel.StringId!].Relationships.AudioStreams.PatchAsync(requestBody); + + // Assert + ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync()).Which; + exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.NotFound); + exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown."); + exception.Errors.Should().HaveCount(2); + + ErrorObject error1 = exception.Errors.ElementAt(0); + error1.Status.Should().Be("404"); + error1.Title.Should().Be("A related resource does not exist."); + error1.Detail.Should().Be($"Related resource of type 'dataStreams' with ID '{unknownAudioStreamId1}' in relationship 'audioStreams' does not exist."); + + ErrorObject error2 = exception.Errors.ElementAt(1); + error2.Status.Should().Be("404"); + error2.Title.Should().Be("A related resource does not exist."); + error2.Detail.Should().Be($"Related resource of type 'dataStreams' with ID '{unknownAudioStreamId2}' in relationship 'audioStreams' does not exist."); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/UpdateResourceTests.cs b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/UpdateResourceTests.cs new file mode 100644 index 0000000000..9c20a8db4e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/UpdateResourceTests.cs @@ -0,0 +1,318 @@ +using System.Net; +using FluentAssertions; +using JsonApiDotNetCore.Resources; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Kiota.Http.HttpClientLibrary; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode; +using OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode.Models; +using OpenApiTests; +using OpenApiTests.RestrictedControllers; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests.RestrictedControllers; + +public sealed class UpdateResourceTests : IClassFixture, RestrictionDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, RestrictionDbContext> _testContext; + private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory; + private readonly RestrictionFakers _fakers = new(); + + public UpdateResourceTests(IntegrationTestContext, RestrictionDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper); + + testContext.UseController(); + + testContext.ConfigureServices(services => services.AddScoped(typeof(IResourceChangeTracker<>), typeof(NeverSameResourceChangeTracker<>))); + } + + [Fact] + public async Task Can_update_resource_with_includes_and_fieldsets() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + existingChannel.UltraHighDefinitionVideoStream = _fakers.DataStream.GenerateOne(); + existingChannel.AudioStreams = _fakers.DataStream.GenerateSet(2); + + DataStream existingVideoStream = _fakers.DataStream.GenerateOne(); + string? newChannelName = _fakers.WriteOnlyChannel.GenerateOne().Name; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + dbContext.DataStreams.Add(existingVideoStream); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + var requestBody = new UpdateWriteOnlyChannelRequestDocument + { + Data = new DataInUpdateWriteOnlyChannelRequest + { + Type = ResourceType.WriteOnlyChannels, + Id = existingChannel.StringId!, + Attributes = new AttributesInUpdateWriteOnlyChannelRequest + { + Name = newChannelName + }, + Relationships = new RelationshipsInUpdateWriteOnlyChannelRequest + { + VideoStream = new ToOneDataStreamInRequest + { + Data = new DataStreamIdentifierInRequest + { + Type = ResourceType.DataStreams, + Id = existingVideoStream.StringId! + } + }, + UltraHighDefinitionVideoStream = new NullableToOneDataStreamInRequest + { + Data = null + }, + AudioStreams = new ToManyDataStreamInRequest + { + Data = [] + } + } + } + }; + + using IDisposable scope = _requestAdapterFactory.WithQueryString(new Dictionary + { + ["include"] = "videoStream,audioStreams", + ["fields[writeOnlyChannels]"] = "name,isCommercial,videoStream,audioStreams", + ["fields[dataStreams]"] = "bytesTransmitted" + }); + + // Act + PrimaryWriteOnlyChannelResponseDocument? response = await apiClient.WriteOnlyChannels[existingChannel.StringId!].PatchAsync(requestBody); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().NotBeNull(); + response.Data.Id.Should().Be(existingChannel.StringId); + response.Data.Attributes.Should().NotBeNull(); + response.Data.Attributes.Name.Should().Be(newChannelName); + response.Data.Attributes.IsCommercial.Should().Be(existingChannel.IsCommercial); + response.Data.Attributes.IsAdultOnly.Should().BeNull(); + response.Data.Relationships.Should().NotBeNull(); + response.Data.Relationships.VideoStream.Should().NotBeNull(); + response.Data.Relationships.VideoStream.Data.Should().NotBeNull(); + response.Data.Relationships.VideoStream.Data.Id.Should().Be(existingVideoStream.StringId); + response.Data.Relationships.UltraHighDefinitionVideoStream.Should().BeNull(); + response.Data.Relationships.AudioStreams.Should().NotBeNull(); + response.Data.Relationships.AudioStreams.Data.Should().BeEmpty(); + + response.Included.Should().HaveCount(1); + response.Included.OfType().Should().ContainSingle(include => include.Id == existingVideoStream.StringId); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + // @formatter:wrap_chained_method_calls chop_always + // @formatter:keep_existing_linebreaks true + + WriteOnlyChannel channelInDatabase = await dbContext.WriteOnlyChannels + .Include(channel => channel.VideoStream) + .Include(channel => channel.UltraHighDefinitionVideoStream) + .Include(channel => channel.AudioStreams) + .FirstWithIdAsync(existingChannel.Id); + + // @formatter:keep_existing_linebreaks restore + // @formatter:wrap_chained_method_calls restore + + channelInDatabase.Name.Should().Be(newChannelName); + channelInDatabase.IsCommercial.Should().Be(existingChannel.IsCommercial); + channelInDatabase.IsAdultOnly.Should().Be(existingChannel.IsAdultOnly); + + channelInDatabase.VideoStream.Should().NotBeNull(); + channelInDatabase.VideoStream.Id.Should().Be(existingVideoStream.Id); + + channelInDatabase.UltraHighDefinitionVideoStream.Should().BeNull(); + + channelInDatabase.AudioStreams.Should().BeEmpty(); + }); + } + + [Fact] + public async Task Can_update_resource_without_attributes_or_relationships() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + existingChannel.UltraHighDefinitionVideoStream = _fakers.DataStream.GenerateOne(); + existingChannel.AudioStreams = _fakers.DataStream.GenerateSet(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + var requestBody = new UpdateWriteOnlyChannelRequestDocument + { + Data = new DataInUpdateWriteOnlyChannelRequest + { + Type = ResourceType.WriteOnlyChannels, + Id = existingChannel.StringId!, + Attributes = new AttributesInUpdateWriteOnlyChannelRequest(), + Relationships = new RelationshipsInUpdateWriteOnlyChannelRequest() + } + }; + + // Act + PrimaryWriteOnlyChannelResponseDocument? response = await apiClient.WriteOnlyChannels[existingChannel.StringId!].PatchAsync(requestBody); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().NotBeNull(); + response.Data.Id.Should().Be(existingChannel.StringId); + response.Data.Attributes.Should().NotBeNull(); + response.Data.Attributes.Name.Should().Be(existingChannel.Name); + response.Data.Attributes.IsCommercial.Should().Be(existingChannel.IsCommercial); + response.Data.Attributes.IsAdultOnly.Should().Be(existingChannel.IsAdultOnly); + response.Data.Relationships.Should().NotBeNull(); + response.Data.Relationships.VideoStream.Should().NotBeNull(); + response.Data.Relationships.VideoStream.Data.Should().BeNull(); + response.Data.Relationships.UltraHighDefinitionVideoStream.Should().NotBeNull(); + response.Data.Relationships.UltraHighDefinitionVideoStream.Data.Should().BeNull(); + response.Data.Relationships.AudioStreams.Should().NotBeNull(); + response.Data.Relationships.AudioStreams.Data.Should().BeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + // @formatter:wrap_chained_method_calls chop_always + // @formatter:keep_existing_linebreaks true + + WriteOnlyChannel channelInDatabase = await dbContext.WriteOnlyChannels + .Include(channel => channel.VideoStream) + .Include(channel => channel.UltraHighDefinitionVideoStream) + .Include(channel => channel.AudioStreams) + .FirstWithIdAsync(existingChannel.Id); + + // @formatter:keep_existing_linebreaks restore + // @formatter:wrap_chained_method_calls restore + + channelInDatabase.Name.Should().Be(existingChannel.Name); + channelInDatabase.IsCommercial.Should().Be(existingChannel.IsCommercial); + channelInDatabase.IsAdultOnly.Should().Be(existingChannel.IsAdultOnly); + + channelInDatabase.VideoStream.Should().NotBeNull(); + channelInDatabase.VideoStream.Id.Should().Be(existingChannel.VideoStream.Id); + + channelInDatabase.UltraHighDefinitionVideoStream.Should().NotBeNull(); + channelInDatabase.UltraHighDefinitionVideoStream.Id.Should().Be(existingChannel.UltraHighDefinitionVideoStream.Id); + + channelInDatabase.AudioStreams.Should().HaveCount(2); + }); + } + + [Fact] + public async Task Cannot_update_resource_for_missing_request_body() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + UpdateWriteOnlyChannelRequestDocument requestBody = null!; + + // Act + Func action = async () => _ = await apiClient.WriteOnlyChannels[existingChannel.StringId!].PatchAsync(requestBody); + + // Assert + await action.Should().ThrowExactlyAsync().WithParameterName("body"); + } + + [Fact] + public async Task Cannot_update_resource_with_unknown_relationship_IDs() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + await dbContext.SaveChangesAsync(); + }); + + string unknownDataStreamId = Unknown.StringId.For(); + + using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory); + var apiClient = new RestrictedControllersClient(requestAdapter); + + var requestBody = new UpdateWriteOnlyChannelRequestDocument + { + Data = new DataInUpdateWriteOnlyChannelRequest + { + Type = ResourceType.WriteOnlyChannels, + Id = existingChannel.StringId!, + Relationships = new RelationshipsInUpdateWriteOnlyChannelRequest + { + VideoStream = new ToOneDataStreamInRequest + { + Data = new DataStreamIdentifierInRequest + { + Type = ResourceType.DataStreams, + Id = unknownDataStreamId + } + }, + AudioStreams = new ToManyDataStreamInRequest + { + Data = + [ + new DataStreamIdentifierInRequest + { + Type = ResourceType.DataStreams, + Id = unknownDataStreamId + } + ] + } + } + } + }; + + // Act + Func action = async () => _ = await apiClient.WriteOnlyChannels[existingChannel.StringId!].PatchAsync(requestBody); + + // Assert + ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync()).Which; + exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.NotFound); + exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown."); + exception.Errors.Should().HaveCount(2); + + ErrorObject error1 = exception.Errors.ElementAt(0); + error1.Status.Should().Be("404"); + error1.Title.Should().Be("A related resource does not exist."); + error1.Detail.Should().Be($"Related resource of type 'dataStreams' with ID '{unknownDataStreamId}' in relationship 'audioStreams' does not exist."); + + ErrorObject error2 = exception.Errors.ElementAt(1); + error2.Status.Should().Be("404"); + error2.Title.Should().Be("A related resource does not exist."); + error2.Detail.Should().Be($"Related resource of type 'dataStreams' with ID '{unknownDataStreamId}' in relationship 'videoStream' does not exist."); + } + + public void Dispose() + { + _requestAdapterFactory.Dispose(); + } +} diff --git a/test/OpenApiKiotaEndToEndTests/TestableHttpClientRequestAdapterFactory.cs b/test/OpenApiKiotaEndToEndTests/TestableHttpClientRequestAdapterFactory.cs new file mode 100644 index 0000000000..0ce536d479 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/TestableHttpClientRequestAdapterFactory.cs @@ -0,0 +1,45 @@ +using JsonApiDotNetCore.OpenApi.Client.Kiota; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.Kiota.Abstractions.Authentication; +using Microsoft.Kiota.Http.HttpClientLibrary; +using TestBuildingBlocks; +using Xunit.Abstractions; + +namespace OpenApiKiotaEndToEndTests; + +internal sealed class TestableHttpClientRequestAdapterFactory : IDisposable +{ + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly SetQueryStringHttpMessageHandler _queryStringMessageHandler = new(); + + public TestableHttpClientRequestAdapterFactory(ITestOutputHelper testOutputHelper) + { + ArgumentNullException.ThrowIfNull(testOutputHelper); + + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + } + + public HttpClientRequestAdapter CreateAdapter(WebApplicationFactory webApplicationFactory) + where TStartup : class + { + ArgumentNullException.ThrowIfNull(webApplicationFactory); + + IList delegatingHandlers = KiotaClientFactory.CreateDefaultHandlers(); + delegatingHandlers.Add(_queryStringMessageHandler); + delegatingHandlers.Add(_logHttpMessageHandler); + HttpClient httpClient = webApplicationFactory.CreateDefaultClient(delegatingHandlers.ToArray()); + + return new HttpClientRequestAdapter(new AnonymousAuthenticationProvider(), httpClient: httpClient); + } + + public IDisposable WithQueryString(IDictionary queryString) + { + return _queryStringMessageHandler.CreateScope(queryString); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + _queryStringMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagClientTests/.editorconfig b/test/OpenApiNSwagClientTests/.editorconfig new file mode 100644 index 0000000000..e2ec1cac44 --- /dev/null +++ b/test/OpenApiNSwagClientTests/.editorconfig @@ -0,0 +1,3 @@ +# Workaround for incorrect nullability in NSwag generated clients. +[*Client.cs] +dotnet_diagnostic.CS8765.severity = none diff --git a/test/OpenApiNSwagClientTests/BaseOpenApiNSwagClientTests.cs b/test/OpenApiNSwagClientTests/BaseOpenApiNSwagClientTests.cs new file mode 100644 index 0000000000..aa73b81824 --- /dev/null +++ b/test/OpenApiNSwagClientTests/BaseOpenApiNSwagClientTests.cs @@ -0,0 +1,72 @@ +using System.Reflection; + +namespace OpenApiNSwagClientTests; + +public abstract class BaseOpenApiNSwagClientTests +{ + /// + /// Sets the property on the specified source to its default value (null for string, 0 for int, false for bool, etc). + /// + protected static object? SetPropertyToDefaultValue(T source, string propertyName) + where T : class + { + ArgumentNullException.ThrowIfNull(source); + ArgumentNullException.ThrowIfNull(propertyName); + + PropertyInfo property = GetExistingProperty(typeof(T), propertyName); + + object? defaultValue = property.PropertyType.IsValueType ? Activator.CreateInstance(property.PropertyType) : null; + property.SetValue(source, defaultValue); + + return defaultValue; + } + + /// + /// Sets the property on the specified source to its initial value, when the type was constructed. This takes the presence of a type initializer into + /// account. + /// + protected static void SetPropertyToInitialValue(T source, string propertyName) + where T : class, new() + { + ArgumentNullException.ThrowIfNull(source); + ArgumentNullException.ThrowIfNull(propertyName); + + var emptyRelationshipsObject = new T(); + object? defaultValue = emptyRelationshipsObject.GetPropertyValue(propertyName); + + source.SetPropertyValue(propertyName, defaultValue); + } + + /// + /// Sets the 'Data' property of the specified relationship to null. + /// + protected static void SetDataPropertyToNull(T source, string relationshipPropertyName) + where T : class + { + ArgumentNullException.ThrowIfNull(source); + ArgumentNullException.ThrowIfNull(relationshipPropertyName); + + PropertyInfo relationshipProperty = GetExistingProperty(typeof(T), relationshipPropertyName); + object? relationshipValue = relationshipProperty.GetValue(source); + + if (relationshipValue == null) + { + throw new InvalidOperationException($"Property '{typeof(T).Name}.{relationshipPropertyName}' is null."); + } + + PropertyInfo dataProperty = GetExistingProperty(relationshipProperty.PropertyType, "Data"); + dataProperty.SetValue(relationshipValue, null); + } + + private static PropertyInfo GetExistingProperty(Type type, string propertyName) + { + PropertyInfo? property = type.GetProperty(propertyName); + + if (property == null) + { + throw new InvalidOperationException($"Type '{type.Name}' does not contain a property named '{propertyName}'."); + } + + return property; + } +} diff --git a/test/OpenApiNSwagClientTests/ChangeTracking/SerializerChangeTrackingTests.cs b/test/OpenApiNSwagClientTests/ChangeTracking/SerializerChangeTrackingTests.cs new file mode 100644 index 0000000000..d14d2ae4c6 --- /dev/null +++ b/test/OpenApiNSwagClientTests/ChangeTracking/SerializerChangeTrackingTests.cs @@ -0,0 +1,846 @@ +using System.Net; +using FluentAssertions; +using JetBrains.Annotations; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using Newtonsoft.Json; +using OpenApiNSwagClientTests.NamingConventions.CamelCase.GeneratedCode; +using OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOn.GeneratedCode; +using TestBuildingBlocks; +using Xunit; + +namespace OpenApiNSwagClientTests.ChangeTracking; + +public sealed class SerializerChangeTrackingTests +{ + [Fact] + public async Task Includes_properties_with_default_values_when_tracked() + { + // Arrange + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOnClient(wrapper.HttpClient); + + string resourceId = Unknown.StringId.Int32; + + var requestBody = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Id = resourceId, + Attributes = new TrackChangesFor(apiClient) + { + Initializer = + { + ValueType = 0, + NullableValueType = null, + NullableReferenceType = null + } + }.Initializer + } + }; + + requestBody.Data.Attributes.RequiredNonNullableReferenceType = "other"; + + // Act + _ = await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(resourceId, null, requestBody)); + + // Assert + wrapper.RequestBody.Should().BeJson($$""" + { + "data": { + "type": "resources", + "id": "{{resourceId}}", + "attributes": { + "openapi:discriminator": "resources", + "requiredNonNullableReferenceType": "other", + "nullableReferenceType": null, + "valueType": 0, + "nullableValueType": null + } + } + } + """); + } + + [Fact] + public async Task Excludes_properties_with_default_values_when_not_tracked() + { + // Arrange + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOnClient(wrapper.HttpClient); + + string resourceId = Unknown.StringId.Int32; + + var requestBody = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Id = resourceId, + Attributes = new TrackChangesFor(apiClient).Initializer + } + }; + + requestBody.Data.Attributes.RequiredNonNullableReferenceType = "other"; + + // Act + _ = await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(resourceId, null, requestBody)); + + // Assert + wrapper.RequestBody.Should().BeJson($$""" + { + "data": { + "type": "resources", + "id": "{{resourceId}}", + "attributes": { + "openapi:discriminator": "resources", + "requiredNonNullableReferenceType": "other" + } + } + } + """); + } + + [Fact] + public async Task Properties_can_be_changed_to_default_values_once_tracked() + { + // Arrange + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOnClient(wrapper.HttpClient); + + string resourceId = Unknown.StringId.Int32; + + var requestBody = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Id = resourceId, + Attributes = new TrackChangesFor(apiClient) + { + Initializer = + { + ValueType = 1, + NullableValueType = 2, + NullableReferenceType = "other" + } + }.Initializer + } + }; + + requestBody.Data.Attributes.ValueType = 0; + requestBody.Data.Attributes.NullableValueType = null; + requestBody.Data.Attributes.NullableReferenceType = null; + + // Act + _ = await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(resourceId, null, requestBody)); + + // Assert + wrapper.RequestBody.Should().BeJson($$""" + { + "data": { + "type": "resources", + "id": "{{resourceId}}", + "attributes": { + "openapi:discriminator": "resources", + "nullableReferenceType": null, + "valueType": 0, + "nullableValueType": null + } + } + } + """); + } + + [Fact] + public async Task Automatically_clears_tracked_properties_after_sending_request() + { + // Arrange + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOnClient(wrapper.HttpClient); + + string resourceId = Unknown.StringId.Int32; + + var requestBody = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Id = resourceId, + Attributes = new TrackChangesFor(apiClient) + { + Initializer = + { + ValueType = 0, + NullableValueType = null, + NullableReferenceType = null + } + }.Initializer + } + }; + + _ = await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(resourceId, null, requestBody)); + wrapper.ChangeResponse(HttpStatusCode.NoContent, null); + + requestBody.Data.Attributes.ValueType = 1; + requestBody.Data.Attributes.RequiredValueType = 2; + requestBody.Data.Attributes.RequiredNullableValueType = 3; + + // Act + _ = await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(resourceId, null, requestBody)); + + // Assert + wrapper.RequestBody.Should().BeJson($$""" + { + "data": { + "type": "resources", + "id": "{{resourceId}}", + "attributes": { + "openapi:discriminator": "resources", + "valueType": 1, + "requiredValueType": 2, + "requiredNullableValueType": 3 + } + } + } + """); + } + + [Fact] + public async Task Can_preserve_tracked_properties_after_sending_request() + { + // Arrange + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + + var apiClient = new NrtOnMsvOnClient(wrapper.HttpClient) + { + AutoClearTracked = false + }; + + string resourceId = Unknown.StringId.Int32; + + var requestBody = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Id = resourceId, + Attributes = new TrackChangesFor(apiClient) + { + Initializer = + { + ValueType = 0, + NullableValueType = null, + NullableReferenceType = null + } + }.Initializer + } + }; + + _ = await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(resourceId, null, requestBody)); + wrapper.ChangeResponse(HttpStatusCode.NoContent, null); + + // Act + _ = await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(resourceId, null, requestBody)); + + // Assert + wrapper.RequestBody.Should().BeJson($$""" + { + "data": { + "type": "resources", + "id": "{{resourceId}}", + "attributes": { + "openapi:discriminator": "resources", + "nullableReferenceType": null, + "valueType": 0, + "nullableValueType": null + } + } + } + """); + } + + [Fact] + public async Task Can_manually_clear_tracked_properties() + { + // Arrange + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + + var apiClient = new NrtOnMsvOnClient(wrapper.HttpClient) + { + AutoClearTracked = false + }; + + string resourceId = Unknown.StringId.Int32; + + var requestBody = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Id = resourceId, + Attributes = new TrackChangesFor(apiClient) + { + Initializer = + { + ValueType = 0, + NullableValueType = null, + NullableReferenceType = null + } + }.Initializer + } + }; + + apiClient.ClearAllTracked(); + + requestBody.Data.Attributes.ValueType = 1; + requestBody.Data.Attributes.RequiredValueType = 2; + requestBody.Data.Attributes.RequiredNullableValueType = 3; + + // Act + _ = await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(resourceId, null, requestBody)); + + // Assert + wrapper.RequestBody.Should().BeJson($$""" + { + "data": { + "type": "resources", + "id": "{{resourceId}}", + "attributes": { + "openapi:discriminator": "resources", + "valueType": 1, + "requiredValueType": 2, + "requiredNullableValueType": 3 + } + } + } + """); + } + + [Fact] + public async Task Can_mark_existing_instance_as_tracked() + { + // Arrange + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOnClient(wrapper.HttpClient); + + string resourceId = Unknown.StringId.Int32; + + var requestBody = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Id = resourceId, + Attributes = new AttributesInUpdateResourceRequest() + } + }; + + apiClient.MarkAsTracked(requestBody.Data.Attributes); + requestBody.Data.Attributes.RequiredNonNullableReferenceType = "other"; + + // Act + _ = await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(resourceId, null, requestBody)); + + // Assert + wrapper.RequestBody.Should().BeJson($$""" + { + "data": { + "type": "resources", + "id": "{{resourceId}}", + "attributes": { + "openapi:discriminator": "resources", + "requiredNonNullableReferenceType": "other" + } + } + } + """); + } + + [Fact] + public async Task Can_mark_properties_on_existing_instance_as_tracked() + { + // Arrange + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOnClient(wrapper.HttpClient); + + string resourceId = Unknown.StringId.Int32; + + var requestBody = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Id = resourceId, + Attributes = new AttributesInUpdateResourceRequest() + } + }; + + string[] propertyNamesToTrack = + [ + nameof(AttributesInUpdateResourceRequest.ValueType), + nameof(AttributesInUpdateResourceRequest.NullableValueType), + nameof(AttributesInUpdateResourceRequest.NullableReferenceType) + ]; + + apiClient.MarkAsTracked(requestBody.Data.Attributes, propertyNamesToTrack); + + // Act + _ = await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(resourceId, null, requestBody)); + + // Assert + wrapper.RequestBody.Should().BeJson($$""" + { + "data": { + "type": "resources", + "id": "{{resourceId}}", + "attributes": { + "openapi:discriminator": "resources", + "nullableReferenceType": null, + "valueType": 0, + "nullableValueType": null + } + } + } + """); + } + + [Fact] + public void Can_recursively_track_properties_on_complex_object() + { + // Arrange + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new ExposeSerializerSettingsOnApiClient(wrapper.HttpClient); + + ComplexType complexObject = new TrackChangesFor(apiClient) + { + Initializer = + { + NullableDateTime = null, + NestedType = new TrackChangesFor(apiClient) + { + Initializer = + { + NullableInt = null, + NullableString = null + } + }.Initializer + } + }.Initializer; + + JsonSerializerSettings serializerSettings = apiClient.GetSerializerSettings(); + + // Act + string json = JsonConvert.SerializeObject(complexObject, serializerSettings); + + // Assert + json.Should().BeJson(""" + { + "NullableDateTime": null, + "NestedType": { + "NullableInt": null, + "NullableString": null + } + } + """); + } + + [Fact] + public async Task Tracking_a_different_instance_of_same_type_upfront_is_isolated() + { + // Arrange + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOnClient(wrapper.HttpClient); + + string resourceId = Unknown.StringId.Int32; + + _ = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Id = resourceId, + Attributes = new TrackChangesFor(apiClient) + { + Initializer = + { + ValueType = 0 + } + }.Initializer + } + }; + + var requestBody = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Id = resourceId, + Attributes = new TrackChangesFor(apiClient) + { + Initializer = + { + NullableValueType = null, + NullableReferenceType = null + } + }.Initializer + } + }; + + // Act + _ = await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(resourceId, null, requestBody)); + + // Assert + wrapper.RequestBody.Should().BeJson($$""" + { + "data": { + "type": "resources", + "id": "{{resourceId}}", + "attributes": { + "openapi:discriminator": "resources", + "nullableReferenceType": null, + "nullableValueType": null + } + } + } + """); + } + + [Fact] + public async Task Tracking_a_different_instance_of_same_type_afterward_is_isolated() + { + // Arrange + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOnClient(wrapper.HttpClient); + + string resourceId = Unknown.StringId.Int32; + + var requestBody = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Id = resourceId, + Attributes = new TrackChangesFor(apiClient) + { + Initializer = + { + NullableValueType = null, + NullableReferenceType = null + } + }.Initializer + } + }; + + _ = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Id = resourceId, + Attributes = new TrackChangesFor(apiClient) + { + Initializer = + { + ValueType = 0 + } + }.Initializer + } + }; + + // Act + _ = await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(resourceId, null, requestBody)); + + // Assert + wrapper.RequestBody.Should().BeJson($$""" + { + "data": { + "type": "resources", + "id": "{{resourceId}}", + "attributes": { + "openapi:discriminator": "resources", + "nullableReferenceType": null, + "nullableValueType": null + } + } + } + """); + } + + [Fact] + public async Task Can_reuse_api_client() + { + // Arrange + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOnClient(wrapper.HttpClient); + + string resourceId = Unknown.StringId.Int32; + + var requestBody1 = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Id = resourceId, + Attributes = new TrackChangesFor(apiClient) + { + Initializer = + { + ValueType = 0 + } + }.Initializer + } + }; + + _ = await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(resourceId, null, requestBody1)); + wrapper.ChangeResponse(HttpStatusCode.NoContent, null); + + var requestBody2 = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Id = resourceId, + Attributes = new TrackChangesFor(apiClient) + { + Initializer = + { + NullableValueType = null, + NullableReferenceType = null + } + }.Initializer + } + }; + + // Act + _ = await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(resourceId, null, requestBody2)); + + // Assert + wrapper.RequestBody.Should().BeJson($$""" + { + "data": { + "type": "resources", + "id": "{{resourceId}}", + "attributes": { + "openapi:discriminator": "resources", + "nullableReferenceType": null, + "nullableValueType": null + } + } + } + """); + } + + [Fact] + public async Task Can_reuse_request_document_on_same_api_client() + { + // Arrange + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOnClient(wrapper.HttpClient); + + string resourceId = Unknown.StringId.Int32; + + var requestBody = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Id = resourceId, + Attributes = new TrackChangesFor(apiClient) + { + Initializer = + { + ValueType = 0, + RequiredNonNullableReferenceType = "first" + } + }.Initializer + } + }; + + _ = await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(resourceId, null, requestBody)); + wrapper.ChangeResponse(HttpStatusCode.NoContent, null); + + requestBody.Data.Attributes.NullableValueType = null; + requestBody.Data.Attributes.NullableReferenceType = null; + requestBody.Data.Attributes.RequiredNonNullableReferenceType = "other"; + + string[] propertyNamesToTrack = + [ + nameof(AttributesInUpdateResourceRequest.NullableValueType), + nameof(AttributesInUpdateResourceRequest.NullableReferenceType) + ]; + + apiClient.MarkAsTracked(requestBody.Data.Attributes, propertyNamesToTrack); + + // Act + _ = await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(resourceId, null, requestBody)); + + // Assert + wrapper.RequestBody.Should().BeJson($$""" + { + "data": { + "type": "resources", + "id": "{{resourceId}}", + "attributes": { + "openapi:discriminator": "resources", + "requiredNonNullableReferenceType": "other", + "nullableReferenceType": null, + "nullableValueType": null + } + } + } + """); + } + + [Fact] + public async Task Can_track_multiple_times_in_same_request_document() + { + // Arrange + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new CamelCaseClient(wrapper.HttpClient); + + var requestBody = new OperationsRequestDocument + { + Atomic_operations = + [ + new UpdateStaffMemberOperation + { + Data = new DataInUpdateStaffMemberRequest + { + Attributes = new TrackChangesFor(apiClient) + { + Initializer = + { + Age = null + } + }.Initializer + } + }, + new UpdateStaffMemberOperation + { + Data = new DataInUpdateStaffMemberRequest + { + Attributes = new TrackChangesFor(apiClient) + { + Initializer = + { + Name = "new-name" + } + }.Initializer + } + }, + new UpdateSupermarketOperation + { + Data = new DataInUpdateSupermarketRequest + { + Attributes = new TrackChangesFor(apiClient) + { + Initializer = + { + NameOfCity = "new-name-of-city" + } + }.Initializer + } + }, + new UpdateSupermarketOperation + { + Data = new DataInUpdateSupermarketRequest + { + Attributes = new TrackChangesFor(apiClient) + { + Initializer = + { + Kind = null + } + }.Initializer + } + } + ] + }; + + // Act + _ = await ApiResponse.TranslateAsync(async () => await apiClient.PostOperationsAsync(requestBody)); + + // Assert + wrapper.RequestBody.Should().BeJson(""" + { + "atomic:operations": [ + { + "openapi:discriminator": "updateStaffMember", + "op": "update", + "data": { + "type": "staffMembers", + "attributes": { + "openapi:discriminator": "staffMembers", + "age": null + } + } + }, + { + "openapi:discriminator": "updateStaffMember", + "op": "update", + "data": { + "type": "staffMembers", + "attributes": { + "openapi:discriminator": "staffMembers", + "name": "new-name" + } + } + }, + { + "openapi:discriminator": "updateSupermarket", + "op": "update", + "data": { + "type": "supermarkets", + "attributes": { + "openapi:discriminator": "supermarkets", + "nameOfCity": "new-name-of-city" + } + } + }, + { + "openapi:discriminator": "updateSupermarket", + "op": "update", + "data": { + "type": "supermarkets", + "attributes": { + "openapi:discriminator": "supermarkets", + "kind": null + } + } + } + ] + } + """); + } + + [UsedImplicitly(ImplicitUseTargetFlags.Members)] + private sealed class ComplexType : NotifyPropertySet + { + private DateTime? _nullableDateTime; + + [JsonProperty(NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)] + public DateTime? NullableDateTime + { + get => _nullableDateTime; + set => SetProperty(ref _nullableDateTime, value); + } + + public NestedType? NestedType { get; set; } + } + + [UsedImplicitly(ImplicitUseTargetFlags.Members)] + private sealed class NestedType : NotifyPropertySet + { + private int? _nullableInt; + private string? _nullableString; + + [JsonProperty(NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)] + public int? NullableInt + { + get => _nullableInt; + set => SetProperty(ref _nullableInt, value); + } + + [JsonProperty(NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)] + public string? NullableString + { + get => _nullableString; + set => SetProperty(ref _nullableString, value); + } + } + + private sealed class ExposeSerializerSettingsOnApiClient(HttpClient httpClient) + : NrtOnMsvOnClient(httpClient) + { + public JsonSerializerSettings GetSerializerSettings() + { + return JsonSerializerSettings; + } + } +} diff --git a/test/OpenApiNSwagClientTests/FakeHttpClientWrapper.cs b/test/OpenApiNSwagClientTests/FakeHttpClientWrapper.cs new file mode 100644 index 0000000000..353933e630 --- /dev/null +++ b/test/OpenApiNSwagClientTests/FakeHttpClientWrapper.cs @@ -0,0 +1,120 @@ +using System.Net; +using System.Net.Http.Headers; +using System.Text; +using System.Text.Json; +using JsonApiDotNetCore.Middleware; + +namespace OpenApiNSwagClientTests; + +/// +/// Enables to inject an outgoing response body and inspect the incoming request. +/// +internal sealed class FakeHttpClientWrapper : IDisposable +{ + private readonly FakeHttpMessageHandler _handler; + + public HttpClient HttpClient { get; } + public HttpRequestMessage? Request => _handler.Request; + public string? RequestBody => _handler.RequestBody; + + private FakeHttpClientWrapper(HttpClient httpClient, FakeHttpMessageHandler handler) + { + HttpClient = httpClient; + _handler = handler; + } + + public JsonElement GetRequestBodyAsJson() + { + if (RequestBody == null) + { + throw new InvalidOperationException("No body was provided with the request."); + } + + using JsonDocument jsonDocument = JsonDocument.Parse(RequestBody); + return jsonDocument.RootElement.Clone(); + } + + public static FakeHttpClientWrapper Create(HttpStatusCode statusCode, string? responseBody) + { +#pragma warning disable CA2000 // Dispose objects before losing scope + // Justification: FakeHttpMessageHandler takes ownership, which is owned by FakeHttpClientWrapper. + HttpResponseMessage response = CreateResponse(statusCode, responseBody); +#pragma warning restore CA2000 // Dispose objects before losing scope + var handler = new FakeHttpMessageHandler(response); + + var httpClient = new HttpClient(handler) + { + BaseAddress = new Uri("http://localhost") + }; + + return new FakeHttpClientWrapper(httpClient, handler); + } + + public void ChangeResponse(HttpStatusCode statusCode, string? responseBody) + { + HttpResponseMessage response = CreateResponse(statusCode, responseBody); + + _handler.SetResponse(response); + } + + private static HttpResponseMessage CreateResponse(HttpStatusCode statusCode, string? responseBody) + { + var response = new HttpResponseMessage(statusCode); + + if (!string.IsNullOrEmpty(responseBody)) + { + response.Content = new StringContent(responseBody, Encoding.UTF8); + response.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(JsonApiMediaType.Default.ToString()); + } + + return response; + } + + public void Dispose() + { + HttpClient.Dispose(); + _handler.Dispose(); + } + + private sealed class FakeHttpMessageHandler(HttpResponseMessage response) : HttpMessageHandler + { + private HttpResponseMessage _response = response; + + public HttpRequestMessage? Request { get; private set; } + public string? RequestBody { get; private set; } + + public void SetResponse(HttpResponseMessage response) + { + ArgumentNullException.ThrowIfNull(response); + + _response = response; + } + + protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken) + { + Request = request; + + // Capture the request body here, before it becomes inaccessible because the request has been disposed. + if (request.Content != null) + { + using Stream stream = request.Content.ReadAsStream(cancellationToken); + using var reader = new StreamReader(stream, Encoding.UTF8); + RequestBody = reader.ReadToEnd(); + } + + return _response; + } + + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + HttpResponseMessage response = Send(request, cancellationToken); + return Task.FromResult(response); + } + + protected override void Dispose(bool disposing) + { + _response.Dispose(); + base.Dispose(disposing); + } + } +} diff --git a/test/OpenApiNSwagClientTests/FakerFactory.cs b/test/OpenApiNSwagClientTests/FakerFactory.cs new file mode 100644 index 0000000000..024dd92287 --- /dev/null +++ b/test/OpenApiNSwagClientTests/FakerFactory.cs @@ -0,0 +1,73 @@ +using System.Reflection; +using AutoBogus; +using JetBrains.Annotations; +using TestBuildingBlocks; + +namespace OpenApiNSwagClientTests; + +internal sealed class FakerFactory +{ + public static FakerFactory Instance { get; } = new(); + + private FakerFactory() + { + } + + public AutoFaker Create() + where TTarget : class + { + return GetDeterministicFaker(); + } + + private static AutoFaker GetDeterministicFaker() + where TTarget : class + { + var autoFaker = new AutoFaker(); + autoFaker.UseDateTimeReference(IntegrationTest.DefaultDateTimeUtc.UtcDateTime); + autoFaker.UseSeed(FakerExtensions.GetFakerSeed()); + return autoFaker; + } + + public AutoFaker CreateForObjectWithResourceId() + where TTarget : class + { + return GetDeterministicFaker().Configure(builder => builder.WithOverride(new ResourceStringIdOverride())); + } + + private sealed class ResourceStringIdOverride : AutoGeneratorOverride + { + // AutoFaker has a class constraint, while TId has not, so we need to wrap it. + private readonly AutoFaker> _idContainerFaker = GetDeterministicFaker>(); + + public override bool CanOverride(AutoGenerateContext context) + { + PropertyInfo? resourceIdPropertyInfo = context.GenerateType.GetProperty("Id"); + return resourceIdPropertyInfo != null && resourceIdPropertyInfo.PropertyType == typeof(string); + } + + public override void Generate(AutoGenerateOverrideContext context) + { + object idValue = _idContainerFaker.GenerateOne().Value!; + idValue = ToPositiveValue(idValue); + + ((dynamic)context.Instance).Id = idValue.ToString()!; + } + + private static object ToPositiveValue(object idValue) + { + return idValue switch + { + short shortValue => Math.Abs(shortValue), + int intValue => Math.Abs(intValue), + long longValue => Math.Abs(longValue), + _ => idValue + }; + } + + [UsedImplicitly(ImplicitUseTargetFlags.Members)] + private sealed class ObjectContainer + { + public TValue? Value { get; set; } + } + } +} diff --git a/test/OpenApiNSwagClientTests/LegacyOpenApi/RequestTests.cs b/test/OpenApiNSwagClientTests/LegacyOpenApi/RequestTests.cs new file mode 100644 index 0000000000..4d153ca80d --- /dev/null +++ b/test/OpenApiNSwagClientTests/LegacyOpenApi/RequestTests.cs @@ -0,0 +1,532 @@ +using System.Net; +using FluentAssertions; +using FluentAssertions.Common; +using FluentAssertions.Extensions; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using Microsoft.Net.Http.Headers; +using OpenApiNSwagClientTests.LegacyOpenApi.GeneratedCode; +using TestBuildingBlocks; +using Xunit; + +namespace OpenApiNSwagClientTests.LegacyOpenApi; + +public sealed class RequestTests +{ + private const string OpenApiMediaType = "application/vnd.api+json; ext=openapi"; + private const string HostPrefix = "http://localhost/api/"; + + [Fact] + public async Task Getting_resource_collection_produces_expected_request() + { + // Arrange + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new LegacyClient(wrapper.HttpClient); + + // Act + _ = await ApiResponse.TranslateAsync(async () => await apiClient.GetFlightCollectionAsync(null, null)); + + // Assert + wrapper.Request.Should().NotBeNull(); + wrapper.Request.Headers.GetValue(HeaderNames.Accept).Should().Be(OpenApiMediaType); + wrapper.Request.Method.Should().Be(HttpMethod.Get); + wrapper.Request.RequestUri.Should().Be($"{HostPrefix}flights"); + wrapper.RequestBody.Should().BeNull(); + } + + [Fact] + public async Task Getting_resource_produces_expected_request() + { + // Arrange + const string flightId = "ZvuH1"; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new LegacyClient(wrapper.HttpClient); + + // Act + _ = await ApiResponse.TranslateAsync(async () => await apiClient.GetFlightAsync(flightId, null, null)); + + // Assert + wrapper.Request.Should().NotBeNull(); + wrapper.Request.Headers.GetValue(HeaderNames.Accept).Should().Be(OpenApiMediaType); + wrapper.Request.Method.Should().Be(HttpMethod.Get); + wrapper.Request.RequestUri.Should().Be($"{HostPrefix}flights/{flightId}"); + wrapper.RequestBody.Should().BeNull(); + } + + [Fact] + public async Task Partial_posting_resource_with_selected_relationships_produces_expected_request() + { + // Arrange + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new LegacyClient(wrapper.HttpClient); + + var requestBody = new CreateFlightRequestDocument + { + Data = new DataInCreateFlightRequest + { + Relationships = new RelationshipsInCreateFlightRequest + { + Purser = new ToOneFlightAttendantInRequest + { + Data = new FlightAttendantIdentifierInRequest + { + Id = "bBJHu" + } + }, + BackupPurser = new NullableToOneFlightAttendantInRequest + { + Data = new FlightAttendantIdentifierInRequest + { + Id = "NInmX" + } + } + } + } + }; + + // Act + _ = await ApiResponse.TranslateAsync(async () => await apiClient.PostFlightAsync(null, requestBody)); + + // Assert + wrapper.Request.Should().NotBeNull(); + wrapper.Request.Headers.GetValue(HeaderNames.Accept).Should().Be(OpenApiMediaType); + wrapper.Request.Method.Should().Be(HttpMethod.Post); + wrapper.Request.RequestUri.Should().Be($"{HostPrefix}flights"); + wrapper.Request.Content.Should().NotBeNull(); + wrapper.Request.Content!.Headers.ContentType.Should().NotBeNull(); + wrapper.Request.Content!.Headers.ContentType!.ToString().Should().Be(OpenApiMediaType); + + wrapper.RequestBody.Should().BeJson(""" + { + "data": { + "type": "flights", + "relationships": { + "openapi:discriminator": "flights", + "purser": { + "data": { + "type": "flight-attendants", + "id": "bBJHu" + } + }, + "backup-purser": { + "data": { + "type": "flight-attendants", + "id": "NInmX" + } + } + } + } + } + """); + } + + [Fact] + public async Task Partial_posting_resource_produces_expected_request() + { + // Arrange + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new LegacyClient(wrapper.HttpClient); + + const char euroSign = '\x20AC'; + const char checkMark = '\x2713'; + const char capitalLWithStroke = '\x0141'; + + string specialCharacters = new(new[] + { + euroSign, + checkMark, + capitalLWithStroke + }); + + string name = $"anAirplaneName {specialCharacters}"; + + var requestBody = new CreateAirplaneRequestDocument + { + Data = new DataInCreateAirplaneRequest + { + Attributes = new TrackChangesFor(apiClient) + { + Initializer = + { + Name = name, + AirtimeInHours = 800, + SerialNumber = null + } + }.Initializer + } + }; + + // Act + _ = await ApiResponse.TranslateAsync(async () => await apiClient.PostAirplaneAsync(null, requestBody)); + + // Assert + wrapper.Request.Should().NotBeNull(); + wrapper.Request.Headers.GetValue(HeaderNames.Accept).Should().Be(OpenApiMediaType); + wrapper.Request.Method.Should().Be(HttpMethod.Post); + wrapper.Request.RequestUri.Should().Be($"{HostPrefix}airplanes"); + wrapper.Request.Content.Should().NotBeNull(); + wrapper.Request.Content!.Headers.ContentType.Should().NotBeNull(); + wrapper.Request.Content!.Headers.ContentType!.ToString().Should().Be(OpenApiMediaType); + + wrapper.RequestBody.Should().BeJson($$""" + { + "data": { + "type": "airplanes", + "attributes": { + "openapi:discriminator": "airplanes", + "name": "{{name}}", + "serial-number": null, + "airtime-in-hours": 800 + } + } + } + """); + } + + [Fact] + public async Task Partial_patching_resource_produces_expected_request() + { + // Arrange + const string airplaneId = "XUuiP"; + var lastServicedAt = 1.January(2021).At(15, 23, 5, 33).ToDateTimeOffset(4.Hours()); + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new LegacyClient(wrapper.HttpClient); + + var requestBody = new UpdateAirplaneRequestDocument + { + Data = new DataInUpdateAirplaneRequest + { + Id = airplaneId, + Attributes = new TrackChangesFor(apiClient) + { + Initializer = + { + LastServicedAt = lastServicedAt, + SerialNumber = null, + IsInMaintenance = false, + AirtimeInHours = null + } + }.Initializer + } + }; + + // Act + _ = await ApiResponse.TranslateAsync(async () => await apiClient.PatchAirplaneAsync(airplaneId, null, requestBody)); + + // Assert + wrapper.Request.Should().NotBeNull(); + wrapper.Request.Headers.GetValue(HeaderNames.Accept).Should().Be(OpenApiMediaType); + wrapper.Request.Method.Should().Be(HttpMethod.Patch); + wrapper.Request.RequestUri.Should().Be($"{HostPrefix}airplanes/{airplaneId}"); + wrapper.Request.Content.Should().NotBeNull(); + wrapper.Request.Content!.Headers.ContentType.Should().NotBeNull(); + wrapper.Request.Content!.Headers.ContentType!.ToString().Should().Be(OpenApiMediaType); + + wrapper.RequestBody.Should().BeJson(""" + { + "data": { + "type": "airplanes", + "id": "XUuiP", + "attributes": { + "openapi:discriminator": "airplanes", + "serial-number": null, + "airtime-in-hours": null, + "last-serviced-at": "2021-01-01T15:23:05.033+04:00", + "is-in-maintenance": false + } + } + } + """); + } + + [Fact] + public async Task Deleting_resource_produces_expected_request() + { + // Arrange + const string flightId = "ZvuH1"; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new LegacyClient(wrapper.HttpClient); + + // Act + await apiClient.DeleteFlightAsync(flightId); + + // Assert + wrapper.Request.Should().NotBeNull(); + wrapper.Request.Method.Should().Be(HttpMethod.Delete); + wrapper.Request.RequestUri.Should().Be($"{HostPrefix}flights/{flightId}"); + wrapper.RequestBody.Should().BeNull(); + } + + [Fact] + public async Task Getting_secondary_resource_produces_expected_request() + { + // Arrange + const string flightId = "ZvuH1"; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new LegacyClient(wrapper.HttpClient); + + // Act + _ = await ApiResponse.TranslateAsync(async () => await apiClient.GetFlightPurserAsync(flightId, null, null)); + + // Assert + wrapper.Request.Should().NotBeNull(); + wrapper.Request.Headers.GetValue(HeaderNames.Accept).Should().Be(OpenApiMediaType); + wrapper.Request.Method.Should().Be(HttpMethod.Get); + wrapper.Request.RequestUri.Should().Be($"{HostPrefix}flights/{flightId}/purser"); + wrapper.RequestBody.Should().BeNull(); + } + + [Fact] + public async Task Getting_secondary_resources_produces_expected_request() + { + // Arrange + const string flightId = "ZvuH1"; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new LegacyClient(wrapper.HttpClient); + + // Act + _ = await ApiResponse.TranslateAsync(async () => await apiClient.GetFlightCabinCrewMembersAsync(flightId, null, null)); + + // Assert + wrapper.Request.Should().NotBeNull(); + wrapper.Request.Headers.GetValue(HeaderNames.Accept).Should().Be(OpenApiMediaType); + wrapper.Request.Method.Should().Be(HttpMethod.Get); + wrapper.Request.RequestUri.Should().Be($"{HostPrefix}flights/{flightId}/cabin-crew-members"); + wrapper.RequestBody.Should().BeNull(); + } + + [Fact] + public async Task Getting_ToOne_relationship_produces_expected_request() + { + // Arrange + const string flightId = "ZvuH1"; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new LegacyClient(wrapper.HttpClient); + + // Act + _ = await ApiResponse.TranslateAsync(async () => await apiClient.GetFlightPurserRelationshipAsync(flightId, null, null)); + + // Assert + wrapper.Request.Should().NotBeNull(); + wrapper.Request.Headers.GetValue(HeaderNames.Accept).Should().Be(OpenApiMediaType); + wrapper.Request.Method.Should().Be(HttpMethod.Get); + wrapper.Request.RequestUri.Should().Be($"{HostPrefix}flights/{flightId}/relationships/purser"); + wrapper.RequestBody.Should().BeNull(); + } + + [Fact] + public async Task Patching_ToOne_relationship_produces_expected_request() + { + // Arrange + const string flightId = "ZvuH1"; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new LegacyClient(wrapper.HttpClient); + + var requestBody = new ToOneFlightAttendantInRequest + { + Data = new FlightAttendantIdentifierInRequest + { + Id = "bBJHu" + } + }; + + // Act + await apiClient.PatchFlightPurserRelationshipAsync(flightId, requestBody); + + // Assert + wrapper.Request.Should().NotBeNull(); + wrapper.Request.Method.Should().Be(HttpMethod.Patch); + wrapper.Request.RequestUri.Should().Be($"{HostPrefix}flights/{flightId}/relationships/purser"); + wrapper.Request.Content.Should().NotBeNull(); + wrapper.Request.Content!.Headers.ContentType.Should().NotBeNull(); + wrapper.Request.Content!.Headers.ContentType!.ToString().Should().Be(OpenApiMediaType); + + wrapper.RequestBody.Should().BeJson(""" + { + "data": { + "type": "flight-attendants", + "id": "bBJHu" + } + } + """); + } + + [Fact] + public async Task Getting_ToMany_relationship_produces_expected_request() + { + // Arrange + const string flightId = "ZvuH1"; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new LegacyClient(wrapper.HttpClient); + + // Act + _ = await ApiResponse.TranslateAsync(async () => await apiClient.GetFlightCabinCrewMembersRelationshipAsync(flightId, null, null)); + + // Assert + wrapper.Request.Should().NotBeNull(); + wrapper.Request.Headers.GetValue(HeaderNames.Accept).Should().Be(OpenApiMediaType); + wrapper.Request.Method.Should().Be(HttpMethod.Get); + wrapper.Request.RequestUri.Should().Be($"{HostPrefix}flights/{flightId}/relationships/cabin-crew-members"); + wrapper.RequestBody.Should().BeNull(); + } + + [Fact] + public async Task Posting_ToMany_relationship_produces_expected_request() + { + // Arrange + const string flightId = "ZvuH1"; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new LegacyClient(wrapper.HttpClient); + + var requestBody = new ToManyFlightAttendantInRequest + { + Data = + [ + new FlightAttendantIdentifierInRequest + { + Id = "bBJHu" + }, + new FlightAttendantIdentifierInRequest + { + Id = "NInmX" + } + ] + }; + + // Act + await apiClient.PostFlightCabinCrewMembersRelationshipAsync(flightId, requestBody); + + // Assert + wrapper.Request.Should().NotBeNull(); + wrapper.Request.Method.Should().Be(HttpMethod.Post); + wrapper.Request.RequestUri.Should().Be($"{HostPrefix}flights/{flightId}/relationships/cabin-crew-members"); + wrapper.Request.Content.Should().NotBeNull(); + wrapper.Request.Content!.Headers.ContentType.Should().NotBeNull(); + wrapper.Request.Content!.Headers.ContentType!.ToString().Should().Be(OpenApiMediaType); + + wrapper.RequestBody.Should().BeJson(""" + { + "data": [ + { + "type": "flight-attendants", + "id": "bBJHu" + }, + { + "type": "flight-attendants", + "id": "NInmX" + } + ] + } + """); + } + + [Fact] + public async Task Patching_ToMany_relationship_produces_expected_request() + { + // Arrange + const string flightId = "ZvuH1"; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new LegacyClient(wrapper.HttpClient); + + var requestBody = new ToManyFlightAttendantInRequest + { + Data = + [ + new FlightAttendantIdentifierInRequest + { + Id = "bBJHu" + }, + new FlightAttendantIdentifierInRequest + { + Id = "NInmX" + } + ] + }; + + // Act + await apiClient.PatchFlightCabinCrewMembersRelationshipAsync(flightId, requestBody); + + // Assert + wrapper.Request.Should().NotBeNull(); + wrapper.Request.Method.Should().Be(HttpMethod.Patch); + wrapper.Request.RequestUri.Should().Be($"{HostPrefix}flights/{flightId}/relationships/cabin-crew-members"); + wrapper.Request.Content.Should().NotBeNull(); + wrapper.Request.Content!.Headers.ContentType.Should().NotBeNull(); + wrapper.Request.Content!.Headers.ContentType!.ToString().Should().Be(OpenApiMediaType); + + wrapper.RequestBody.Should().BeJson(""" + { + "data": [ + { + "type": "flight-attendants", + "id": "bBJHu" + }, + { + "type": "flight-attendants", + "id": "NInmX" + } + ] + } + """); + } + + [Fact] + public async Task Deleting_ToMany_relationship_produces_expected_request() + { + // Arrange + const string flightId = "ZvuH1"; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new LegacyClient(wrapper.HttpClient); + + var requestBody = new ToManyFlightAttendantInRequest + { + Data = + [ + new FlightAttendantIdentifierInRequest + { + Id = "bBJHu" + }, + new FlightAttendantIdentifierInRequest + { + Id = "NInmX" + } + ] + }; + + // Act + await apiClient.DeleteFlightCabinCrewMembersRelationshipAsync(flightId, requestBody); + + // Assert + wrapper.Request.Should().NotBeNull(); + wrapper.Request.Method.Should().Be(HttpMethod.Delete); + wrapper.Request.RequestUri.Should().Be($"{HostPrefix}flights/{flightId}/relationships/cabin-crew-members"); + wrapper.Request.Content.Should().NotBeNull(); + wrapper.Request.Content!.Headers.ContentType.Should().NotBeNull(); + wrapper.Request.Content!.Headers.ContentType!.ToString().Should().Be(OpenApiMediaType); + + wrapper.RequestBody.Should().BeJson(""" + { + "data": [ + { + "type": "flight-attendants", + "id": "bBJHu" + }, + { + "type": "flight-attendants", + "id": "NInmX" + } + ] + } + """); + } +} diff --git a/test/OpenApiNSwagClientTests/LegacyOpenApi/ResponseTests.cs b/test/OpenApiNSwagClientTests/LegacyOpenApi/ResponseTests.cs new file mode 100644 index 0000000000..0da98c30af --- /dev/null +++ b/test/OpenApiNSwagClientTests/LegacyOpenApi/ResponseTests.cs @@ -0,0 +1,722 @@ +using System.Globalization; +using System.Net; +using FluentAssertions; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using OpenApiNSwagClientTests.LegacyOpenApi.GeneratedCode; +using Xunit; + +namespace OpenApiNSwagClientTests.LegacyOpenApi; + +public sealed class ResponseTests +{ + private const string HostPrefix = "http://localhost/api/"; + + [Fact] + public async Task Getting_resource_collection_translates_response() + { + // Arrange + const string flightId = "ZvuH1"; + const string flightDestination = "Amsterdam"; + const string flightServiceOnBoard = "Movies"; + const string flightDepartsAt = "2014-11-25T00:00:00"; + const string documentMetaValue = "1"; + const string flightMetaValue = "https://api.jsonapi.net/docs/#get-flights"; + const string purserMetaValue = "https://api.jsonapi.net/docs/#get-flight-purser"; + const string cabinCrewMembersMetaValue = "https://api.jsonapi.net/docs/#get-flight-cabin-crew-members"; + const string passengersMetaValue = "https://api.jsonapi.net/docs/#get-flight-passengers"; + const string topLevelLink = $"{HostPrefix}flights"; + const string flightResourceLink = $"{topLevelLink}/{flightId}"; + + const string responseBody = $$""" + { + "meta": { + "total-resources": "{{documentMetaValue}}" + }, + "links": { + "self": "{{topLevelLink}}", + "first": "{{topLevelLink}}", + "last": "{{topLevelLink}}" + }, + "data": [ + { + "type": "flights", + "id": "{{flightId}}", + "attributes": { + "final-destination": "{{flightDestination}}", + "stop-over-destination": null, + "operated-by": "DeltaAirLines", + "departs-at": "{{flightDepartsAt}}", + "arrives-at": null, + "services-on-board": [ + "{{flightServiceOnBoard}}", + "", + null + ] + }, + "relationships": { + "purser": { + "links": { + "self": "{{flightResourceLink}}/relationships/purser", + "related": "{{flightResourceLink}}/purser" + }, + "meta": { + "docs": "{{purserMetaValue}}" + } + }, + "cabin-crew-members": { + "links": { + "self": "{{flightResourceLink}}/relationships/cabin-crew-members", + "related": "{{flightResourceLink}}/cabin-crew-members" + }, + "meta": { + "docs": "{{cabinCrewMembersMetaValue}}" + } + }, + "passengers": { + "links": { + "self": "{{flightResourceLink}}/relationships/passengers", + "related": "{{flightResourceLink}}/passengers" + }, + "meta": { + "docs": "{{passengersMetaValue}}" + } + } + }, + "links": { + "self": "{{flightResourceLink}}" + }, + "meta": { + "docs": "{{flightMetaValue}}" + } + } + ] + } + """; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.OK, responseBody); + var apiClient = new LegacyClient(wrapper.HttpClient); + + // Act + FlightCollectionResponseDocument response = await apiClient.GetFlightCollectionAsync(null, null); + + // Assert + response.Jsonapi.Should().BeNull(); + response.Meta.Should().HaveCount(1); + response.Meta["total-resources"].Should().Be(documentMetaValue); + response.Links.Self.Should().Be(topLevelLink); + response.Links.First.Should().Be(topLevelLink); + response.Links.Last.Should().Be(topLevelLink); + response.Data.Should().HaveCount(1); + + DataInFlightResponse flight = response.Data.First(); + flight.Id.Should().Be(flightId); + flight.Links.Self.Should().Be(flightResourceLink); + flight.Meta.Should().HaveCount(1); + flight.Meta["docs"].Should().Be(flightMetaValue); + + flight.Attributes.FinalDestination.Should().Be(flightDestination); + flight.Attributes.StopOverDestination.Should().BeNull(); + flight.Attributes.ServicesOnBoard.Should().HaveCount(3); + flight.Attributes.ServicesOnBoard.ElementAt(0).Should().Be(flightServiceOnBoard); + flight.Attributes.ServicesOnBoard.ElementAt(1).Should().Be(string.Empty); + flight.Attributes.ServicesOnBoard.ElementAt(2).Should().BeNull(); + flight.Attributes.OperatedBy.Should().Be(Airline.DeltaAirLines); + flight.Attributes.DepartsAt.Should().Be(DateTimeOffset.Parse(flightDepartsAt, new CultureInfo("en-GB"))); + flight.Attributes.ArrivesAt.Should().BeNull(); + + flight.Relationships.Purser.Data.Should().BeNull(); + flight.Relationships.Purser.Links.Self.Should().Be($"{flightResourceLink}/relationships/purser"); + flight.Relationships.Purser.Links.Related.Should().Be($"{flightResourceLink}/purser"); + flight.Relationships.Purser.Meta.Should().HaveCount(1); + flight.Relationships.Purser.Meta["docs"].Should().Be(purserMetaValue); + + flight.Relationships.CabinCrewMembers.Data.Should().BeNull(); + flight.Relationships.CabinCrewMembers.Links.Self.Should().Be($"{flightResourceLink}/relationships/cabin-crew-members"); + flight.Relationships.CabinCrewMembers.Links.Related.Should().Be($"{flightResourceLink}/cabin-crew-members"); + flight.Relationships.CabinCrewMembers.Meta.Should().HaveCount(1); + flight.Relationships.CabinCrewMembers.Meta["docs"].Should().Be(cabinCrewMembersMetaValue); + + flight.Relationships.Passengers.Data.Should().BeNull(); + flight.Relationships.Passengers.Links.Self.Should().Be($"{flightResourceLink}/relationships/passengers"); + flight.Relationships.Passengers.Links.Related.Should().Be($"{flightResourceLink}/passengers"); + flight.Relationships.Passengers.Meta.Should().HaveCount(1); + flight.Relationships.Passengers.Meta["docs"].Should().Be(passengersMetaValue); + } + + [Fact] + public async Task Getting_resource_translates_response() + { + // Arrange + const string flightId = "ZvuH1"; + const string departsAtInZuluTime = "2021-06-08T12:53:30.554Z"; + const string flightDestination = "Amsterdam"; + const string arrivesAtWithUtcOffset = "2019-02-20T11:56:33.0721266+01:00"; + const string flightServiceOnBoard = "Movies"; + + const string responseBody = $$""" + { + "links": { + "self": "{{HostPrefix}}flights/{{flightId}}&fields[flights]=departs-at,arrives-at" + }, + "data": { + "type": "flights", + "id": "{{flightId}}", + "attributes": { + "departs-at": "{{departsAtInZuluTime}}", + "arrives-at": "{{arrivesAtWithUtcOffset}}", + "final-destination": "{{flightDestination}}", + "services-on-board": ["{{flightServiceOnBoard}}"] + }, + "links": { + "self": "{{HostPrefix}}flights/{{flightId}}" + } + } + } + """; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.OK, responseBody); + var apiClient = new LegacyClient(wrapper.HttpClient); + + // Act + PrimaryFlightResponseDocument response = await apiClient.GetFlightAsync(flightId, null, null); + + // Assert + response.Jsonapi.Should().BeNull(); + response.Meta.Should().BeNull(); + response.Data.Meta.Should().BeNull(); + response.Data.Relationships.Should().BeNull(); + response.Data.Attributes.DepartsAt.Should().Be(DateTimeOffset.Parse(departsAtInZuluTime)); + response.Data.Attributes.ArrivesAt.Should().Be(DateTimeOffset.Parse(arrivesAtWithUtcOffset)); + response.Data.Attributes.ServicesOnBoard.Should().Contain(flightServiceOnBoard); + response.Data.Attributes.FinalDestination.Should().Be(flightDestination); + response.Data.Attributes.StopOverDestination.Should().BeNull(); + response.Data.Attributes.OperatedBy.Should().Be(default); + } + + [Fact] + public async Task Getting_unknown_resource_translates_error_response() + { + // Arrange + const string flightId = "ZvuH1"; + + const string responseBody = $$""" + { + "links": { + "self": "http://localhost/api/flights/ZvuH1", + "describedby": "/swagger/v1/swagger.json" + }, + "errors": [ + { + "id": "f1a520ac-02a0-466b-94ea-86cbaa86f02f", + "status": "404", + "title": "The requested resource does not exist.", + "detail": "Resource of type 'flights' with ID '{{flightId}}' does not exist." + } + ] + } + """; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NotFound, responseBody); + var apiClient = new LegacyClient(wrapper.HttpClient); + + // Act + Func action = async () => await apiClient.GetFlightAsync(flightId, null, null); + + // Assert + ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; + exception.StatusCode.Should().Be((int)HttpStatusCode.NotFound); + exception.Result.Links.Should().NotBeNull(); + exception.Result.Links.Self.Should().Be("http://localhost/api/flights/ZvuH1"); + exception.Result.Links.Describedby.Should().Be("/swagger/v1/swagger.json"); + exception.Result.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Result.Errors.ElementAt(0); + error.Id.Should().Be("f1a520ac-02a0-466b-94ea-86cbaa86f02f"); + error.Status.Should().Be("404"); + error.Title.Should().Be("The requested resource does not exist."); + error.Detail.Should().Be($"Resource of type 'flights' with ID '{flightId}' does not exist."); + error.Source.Should().BeNull(); + } + + [Fact] + public async Task Posting_resource_translates_response() + { + // Arrange + const string flightId = "ZvuH1"; + const string flightAttendantId = "bBJHu"; + + const string responseBody = $$""" + { + "links": { + "self": "{{HostPrefix}}flights/{{flightId}}&fields[flights]&include=purser,cabin-crew-members,passengers" + }, + "data": { + "type": "flights", + "id": "{{flightId}}", + "relationships": { + "purser": { + "links": { + "self": "{{HostPrefix}}flights/{{flightId}}/relationships/purser", + "related": "{{HostPrefix}}flights/{{flightId}}/purser" + }, + "data": { + "type": "flight-attendants", + "id": "{{flightAttendantId}}" + } + }, + "cabin-crew-members": { + "links": { + "self": "{{HostPrefix}}flights/{{flightId}}/relationships/cabin-crew-members", + "related": "{{HostPrefix}}flights/{{flightId}}/cabin-crew-members" + }, + "data": [ + { + "type": "flight-attendants", + "id": "{{flightAttendantId}}" + } + ], + }, + "passengers": { + "links": { + "self": "{{HostPrefix}}flights/{{flightId}}/relationships/passengers", + "related": "{{HostPrefix}}flights/{{flightId}}/passengers" + }, + "data": [ ] + } + }, + "links": { + "self": "{{HostPrefix}}flights/{{flightId}}&fields[flights]&include=purser,cabin-crew-members,passengers" + } + } + } + """; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.Created, responseBody); + var apiClient = new LegacyClient(wrapper.HttpClient); + + var requestBody = new CreateFlightRequestDocument + { + Data = new DataInCreateFlightRequest + { + Relationships = new RelationshipsInCreateFlightRequest + { + Purser = new ToOneFlightAttendantInRequest + { + Data = new FlightAttendantIdentifierInRequest + { + Id = flightAttendantId + } + } + } + } + }; + + // Act + PrimaryFlightResponseDocument response = await apiClient.PostFlightAsync(null, requestBody); + + // Assert + response.Data.Attributes.Should().BeNull(); + response.Data.Relationships.Purser.Data.Should().NotBeNull(); + response.Data.Relationships.Purser.Data.Id.Should().Be(flightAttendantId); + response.Data.Relationships.CabinCrewMembers.Data.Should().HaveCount(1); + response.Data.Relationships.CabinCrewMembers.Data.First().Id.Should().Be(flightAttendantId); + response.Data.Relationships.CabinCrewMembers.Data.First().Type.Should().Be(FlightAttendantResourceType.FlightAttendants); + response.Data.Relationships.Passengers.Data.Should().BeEmpty(); + } + + [Fact] + public async Task Patching_resource_with_side_effects_translates_response() + { + // Arrange + const string flightId = "ZvuH1"; + + const string responseBody = $$""" + { + "links": { + "self": "{{HostPrefix}}flights/{{flightId}}&fields[flights]" + }, + "data": { + "type": "flights", + "id": "{{flightId}}", + "links": { + "self": "{{HostPrefix}}flights/{{flightId}}&fields[flights]&include=purser,cabin-crew-members,passengers" + } + } + } + """; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.OK, responseBody); + var apiClient = new LegacyClient(wrapper.HttpClient); + + var requestBody = new UpdateFlightRequestDocument + { + Data = new DataInUpdateFlightRequest + { + Id = flightId + } + }; + + // Act + PrimaryFlightResponseDocument response = await apiClient.PatchFlightAsync(flightId, null, requestBody); + + // Assert + response.Data.Attributes.Should().BeNull(); + response.Data.Relationships.Should().BeNull(); + } + + [Fact] + public async Task Patching_resource_without_side_effects_translates_response() + { + // Arrange + const string flightId = "ZvuH1"; + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new LegacyClient(wrapper.HttpClient); + + // Act + PrimaryFlightResponseDocument? response = await ApiResponse.TranslateAsync(async () => await apiClient.PatchFlightAsync(flightId, null, + new UpdateFlightRequestDocument + { + Data = new DataInUpdateFlightRequest + { + Id = flightId + } + })); + + // Assert + response.Should().BeNull(); + } + + [Fact] + public async Task Deleting_resource_produces_empty_response() + { + // Arrange + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new LegacyClient(wrapper.HttpClient); + + // Act + Func action = async () => await apiClient.DeleteFlightAsync("ZvuH1"); + + // Assert + await action.Should().NotThrowAsync(); + } + + [Fact] + public async Task Getting_secondary_resource_translates_response() + { + // Arrange + const string flightId = "ZvuH1"; + const string purserId = "bBJHu"; + const string emailAddress = "email@example.com"; + const string age = "20"; + const string profileImageUrl = "www.image.com"; + const string distanceTraveledInKilometer = "5000"; + + const string responseBody = $$""" + { + "links": { + "self": "{{HostPrefix}}flights/{{flightId}}/purser", + "first": "{{HostPrefix}}flights/{{flightId}}/purser", + "last": "{{HostPrefix}}flights/{{flightId}}/purser" + }, + "data": { + "type": "flight-attendants", + "id": "{{purserId}}", + "attributes": { + "email-address": "{{emailAddress}}", + "age": "{{age}}", + "profile-image-url": "{{profileImageUrl}}", + "distance-traveled-in-kilometers": "{{distanceTraveledInKilometer}}", + }, + "relationships": { + "scheduled-for-flights": { + "links": { + "self": "{{HostPrefix}}flight-attendants/{{purserId}}/relationships/scheduled-for-flights", + "related": "{{HostPrefix}}flight-attendants/{{purserId}}/scheduled-for-flights" + } + }, + "purser-on-flights": { + "links": { + "self": "{{HostPrefix}}flight-attendants/{{purserId}}/relationships/purser-on-flights", + "related": "{{HostPrefix}}flight-attendants/{{purserId}}/purser-on-flights" + } + }, + }, + "links": { + "self": "{{HostPrefix}}flight-attendants/{{purserId}}", + } + } + } + """; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.OK, responseBody); + var apiClient = new LegacyClient(wrapper.HttpClient); + + // Act + SecondaryFlightAttendantResponseDocument response = await apiClient.GetFlightPurserAsync(flightId, null, null); + + // Assert + response.Data.Should().NotBeNull(); + response.Data.Id.Should().Be(purserId); + response.Data.Attributes.EmailAddress.Should().Be(emailAddress); + response.Data.Attributes.Age.Should().Be(int.Parse(age)); + response.Data.Attributes.ProfileImageUrl.Should().Be(profileImageUrl); + response.Data.Attributes.DistanceTraveledInKilometers.Should().Be(int.Parse(distanceTraveledInKilometer)); + } + + [Fact] + public async Task Getting_nullable_secondary_resource_translates_response() + { + // Arrange + const string flightId = "ZvuH1"; + + const string responseBody = $$""" + { + "links": { + "self": "{{HostPrefix}}flights/{{flightId}}/backup-purser", + "first": "{{HostPrefix}}flights/{{flightId}}/backup-purser", + "last": "{{HostPrefix}}flights/{{flightId}}/backup-purser" + }, + "data": null + } + """; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.OK, responseBody); + var apiClient = new LegacyClient(wrapper.HttpClient); + + // Act + NullableSecondaryFlightAttendantResponseDocument response = await apiClient.GetFlightBackupPurserAsync(flightId, null, null); + + // Assert + response.Data.Should().BeNull(); + } + + [Fact] + public async Task Getting_secondary_resources_translates_response() + { + // Arrange + const string flightId = "ZvuH1"; + + const string responseBody = $$""" + { + "links": { + "self": "{{HostPrefix}}flights/{{flightId}}/cabin-crew-members", + "first": "{{HostPrefix}}flights/{{flightId}}/cabin-crew-members" + }, + "data": [ ] + } + """; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.OK, responseBody); + var apiClient = new LegacyClient(wrapper.HttpClient); + + // Act + FlightAttendantCollectionResponseDocument response = await apiClient.GetFlightCabinCrewMembersAsync(flightId, null, null); + + // Assert + response.Data.Should().BeEmpty(); + } + + [Fact] + public async Task Getting_nullable_ToOne_relationship_translates_response() + { + // Arrange + const string flightId = "ZvuH1"; + + const string responseBody = $$""" + { + "links": { + "self": "{{HostPrefix}}flights/{{flightId}}/relationships/backup-purser", + "related": "{{HostPrefix}}flights/{{flightId}}/relationships/backup-purser" + }, + "data": null + } + """; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.OK, responseBody); + var apiClient = new LegacyClient(wrapper.HttpClient); + + // Act + NullableFlightAttendantIdentifierResponseDocument response = await apiClient.GetFlightBackupPurserRelationshipAsync(flightId, null, null); + + // Assert + response.Data.Should().BeNull(); + } + + [Fact] + public async Task Getting_ToOne_relationship_translates_response() + { + // Arrange + const string flightId = "ZvuH1"; + const string purserId = "bBJHu"; + + const string responseBody = $$""" + { + "links": { + "self": "{{HostPrefix}}flights/{{flightId}}/relationships/purser", + "related": "{{HostPrefix}}flights/{{flightId}}/relationships/purser" + }, + "data": { + "type": "flight-attendants", + "id": "{{purserId}}" + } + } + """; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.OK, responseBody); + var apiClient = new LegacyClient(wrapper.HttpClient); + + // Act + FlightAttendantIdentifierResponseDocument response = await apiClient.GetFlightPurserRelationshipAsync(flightId, null, null); + + // Assert + response.Data.Should().NotBeNull(); + response.Data.Id.Should().Be(purserId); + response.Data.Type.Should().Be(FlightAttendantResourceType.FlightAttendants); + } + + [Fact] + public async Task Patching_ToOne_relationship_translates_response() + { + // Arrange + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new LegacyClient(wrapper.HttpClient); + + var requestBody = new ToOneFlightAttendantInRequest + { + Data = new FlightAttendantIdentifierInRequest + { + Id = "Adk2a" + } + }; + + // Act + await apiClient.PatchFlightPurserRelationshipAsync("ZvuH1", requestBody); + } + + [Fact] + public async Task Getting_ToMany_relationship_translates_response() + { + // Arrange + const string flightId = "ZvuH1"; + const string flightAttendantId1 = "bBJHu"; + const string flightAttendantId2 = "ZvuHNInmX1"; + + const string responseBody = $$""" + { + "links": { + "self": "{{HostPrefix}}flights/{{flightId}}/relationships/cabin-crew-members", + "related": "{{HostPrefix}}flights/{{flightId}}/relationships/cabin-crew-members", + "first": "{{HostPrefix}}flights/{{flightId}}/relationships/cabin-crew-members" + }, + "data": [{ + "type": "flight-attendants", + "id": "{{flightAttendantId1}}" + }, + { + "type": "flight-attendants", + "id": "{{flightAttendantId2}}" + }] + } + """; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.OK, responseBody); + var apiClient = new LegacyClient(wrapper.HttpClient); + + // Act + FlightAttendantIdentifierCollectionResponseDocument response = await apiClient.GetFlightCabinCrewMembersRelationshipAsync(flightId, null, null); + + // Assert + response.Data.Should().HaveCount(2); + response.Data.First().Id.Should().Be(flightAttendantId1); + response.Data.First().Type.Should().Be(FlightAttendantResourceType.FlightAttendants); + response.Data.Last().Id.Should().Be(flightAttendantId2); + response.Data.Last().Type.Should().Be(FlightAttendantResourceType.FlightAttendants); + } + + [Fact] + public async Task Posting_ToMany_relationship_produces_empty_response() + { + // Arrange + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new LegacyClient(wrapper.HttpClient); + + var requestBody = new ToManyFlightAttendantInRequest + { + Data = + [ + new FlightAttendantIdentifierInRequest + { + Id = "Adk2a" + }, + new FlightAttendantIdentifierInRequest + { + Id = "Un37k" + } + ] + }; + + // Act + Func action = async () => await apiClient.PostFlightCabinCrewMembersRelationshipAsync("ZvuH1", requestBody); + + // Assert + await action.Should().NotThrowAsync(); + } + + [Fact] + public async Task Patching_ToMany_relationship_produces_empty_response() + { + // Arrange + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new LegacyClient(wrapper.HttpClient); + + var requestBody = new ToManyFlightAttendantInRequest + { + Data = + [ + new FlightAttendantIdentifierInRequest + { + Id = "Adk2a" + }, + new FlightAttendantIdentifierInRequest + { + Id = "Un37k" + } + ] + }; + + // Act + Func action = async () => await apiClient.PatchFlightCabinCrewMembersRelationshipAsync("ZvuH1", requestBody); + + // Assert + await action.Should().NotThrowAsync(); + } + + [Fact] + public async Task Deleting_ToMany_relationship_produces_empty_response() + { + // Arrange + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new LegacyClient(wrapper.HttpClient); + + var requestBody = new ToManyFlightAttendantInRequest + { + Data = + [ + new FlightAttendantIdentifierInRequest + { + Id = "Adk2a" + }, + new FlightAttendantIdentifierInRequest + { + Id = "Un37k" + } + ] + }; + + // Act + Func action = async () => await apiClient.DeleteFlightCabinCrewMembersRelationshipAsync("ZvuH1", requestBody); + + // Assert + await action.Should().NotThrowAsync(); + } +} diff --git a/test/OpenApiNSwagClientTests/NamingConventions/CamelCase/GeneratedTypesTests.cs b/test/OpenApiNSwagClientTests/NamingConventions/CamelCase/GeneratedTypesTests.cs new file mode 100644 index 0000000000..6828e96d32 --- /dev/null +++ b/test/OpenApiNSwagClientTests/NamingConventions/CamelCase/GeneratedTypesTests.cs @@ -0,0 +1,203 @@ +using OpenApiNSwagClientTests.NamingConventions.CamelCase.GeneratedCode; +using Xunit; +using GeneratedClient = OpenApiNSwagClientTests.NamingConventions.CamelCase.GeneratedCode.CamelCaseClient; + +namespace OpenApiNSwagClientTests.NamingConventions.CamelCase; + +public sealed class GeneratedTypesTests +{ + [Fact] + public void Generated_endpoint_methods_are_named_as_expected() + { + _ = nameof(GeneratedClient.GetSupermarketCollectionAsync); + _ = nameof(GeneratedClient.HeadSupermarketCollectionAsync); + _ = nameof(GeneratedClient.PostSupermarketAsync); + _ = nameof(GeneratedClient.GetSupermarketAsync); + _ = nameof(GeneratedClient.HeadSupermarketAsync); + _ = nameof(GeneratedClient.PatchSupermarketAsync); + _ = nameof(GeneratedClient.DeleteSupermarketAsync); + _ = nameof(GeneratedClient.GetSupermarketBackupStoreManagerAsync); + _ = nameof(GeneratedClient.HeadSupermarketBackupStoreManagerAsync); + _ = nameof(GeneratedClient.GetSupermarketBackupStoreManagerRelationshipAsync); + _ = nameof(GeneratedClient.HeadSupermarketBackupStoreManagerRelationshipAsync); + _ = nameof(GeneratedClient.PatchSupermarketBackupStoreManagerRelationshipAsync); + _ = nameof(GeneratedClient.GetSupermarketCashiersAsync); + _ = nameof(GeneratedClient.HeadSupermarketCashiersAsync); + _ = nameof(GeneratedClient.GetSupermarketCashiersRelationshipAsync); + _ = nameof(GeneratedClient.HeadSupermarketCashiersRelationshipAsync); + _ = nameof(GeneratedClient.PostSupermarketCashiersRelationshipAsync); + _ = nameof(GeneratedClient.PatchSupermarketCashiersRelationshipAsync); + _ = nameof(GeneratedClient.DeleteSupermarketCashiersRelationshipAsync); + _ = nameof(GeneratedClient.GetSupermarketStoreManagerAsync); + _ = nameof(GeneratedClient.HeadSupermarketStoreManagerAsync); + _ = nameof(GeneratedClient.GetSupermarketStoreManagerRelationshipAsync); + _ = nameof(GeneratedClient.HeadSupermarketStoreManagerRelationshipAsync); + _ = nameof(GeneratedClient.PatchSupermarketStoreManagerRelationshipAsync); + + _ = nameof(GeneratedClient.GetStaffMemberCollectionAsync); + _ = nameof(GeneratedClient.HeadStaffMemberCollectionAsync); + _ = nameof(GeneratedClient.PostStaffMemberAsync); + _ = nameof(GeneratedClient.GetStaffMemberAsync); + _ = nameof(GeneratedClient.HeadStaffMemberAsync); + _ = nameof(GeneratedClient.PatchStaffMemberAsync); + _ = nameof(GeneratedClient.DeleteStaffMemberAsync); + + _ = nameof(GeneratedClient.PostOperationsAsync); + } + + [Fact] + public void Generated_top_level_document_types_are_named_as_expected() + { + _ = nameof(SupermarketCollectionResponseDocument.Meta); + _ = nameof(CreateSupermarketRequestDocument.Meta); + _ = nameof(PrimarySupermarketResponseDocument.Meta); + _ = nameof(UpdateSupermarketRequestDocument.Meta); + + _ = nameof(StaffMemberCollectionResponseDocument.Meta); + _ = nameof(CreateStaffMemberRequestDocument.Meta); + _ = nameof(PrimaryStaffMemberResponseDocument.Meta); + _ = nameof(UpdateStaffMemberRequestDocument.Meta); + _ = nameof(StaffMemberIdentifierCollectionResponseDocument.Meta); + _ = nameof(StaffMemberIdentifierResponseDocument.Meta); + _ = nameof(SecondaryStaffMemberResponseDocument.Meta); + _ = nameof(NullableSecondaryStaffMemberResponseDocument.Meta); + _ = nameof(NullableStaffMemberIdentifierResponseDocument.Meta); + + _ = nameof(ErrorResponseDocument.Meta); + + _ = nameof(OperationsRequestDocument.Meta); + _ = nameof(OperationsResponseDocument.Meta); + } + + [Fact] + public void Generated_link_types_are_named_as_expected() + { + _ = nameof(ResourceTopLevelLinks); + _ = nameof(ResourceCollectionTopLevelLinks); + _ = nameof(ResourceIdentifierTopLevelLinks); + _ = nameof(ResourceIdentifierCollectionTopLevelLinks); + _ = nameof(ErrorTopLevelLinks); + _ = nameof(ResourceLinks); + _ = nameof(RelationshipLinks); + _ = nameof(ErrorLinks); + } + + [Fact] + public void Generated_operation_types_are_named_as_expected() + { + _ = nameof(CreateSupermarketOperation.Meta); + _ = nameof(UpdateSupermarketOperation.Meta); + _ = nameof(DeleteSupermarketOperation.Meta); + _ = nameof(UpdateSupermarketBackupStoreManagerRelationshipOperation.Meta); + _ = nameof(UpdateSupermarketCashiersRelationshipOperation.Meta); + _ = nameof(AddToSupermarketCashiersRelationshipOperation.Meta); + _ = nameof(RemoveFromSupermarketCashiersRelationshipOperation.Meta); + _ = nameof(UpdateSupermarketStoreManagerRelationshipOperation.Meta); + + _ = nameof(CreateStaffMemberOperation.Meta); + _ = nameof(UpdateStaffMemberOperation.Meta); + _ = nameof(DeleteStaffMemberOperation.Meta); + } + + [Fact] + public void Generated_resource_field_types_are_named_as_expected() + { + _ = nameof(AttributesInCreateSupermarketRequest.NameOfCity); + _ = nameof(AttributesInCreateSupermarketRequest.Kind); + _ = nameof(AttributesInUpdateSupermarketRequest.NameOfCity); + _ = nameof(AttributesInUpdateSupermarketRequest.Kind); + _ = nameof(AttributesInSupermarketResponse.NameOfCity); + _ = nameof(AttributesInSupermarketResponse.Kind); + _ = nameof(RelationshipsInCreateSupermarketRequest.StoreManager); + _ = nameof(RelationshipsInCreateSupermarketRequest.BackupStoreManager); + _ = nameof(RelationshipsInCreateSupermarketRequest.Cashiers); + _ = nameof(RelationshipsInUpdateSupermarketRequest.StoreManager); + _ = nameof(RelationshipsInUpdateSupermarketRequest.BackupStoreManager); + _ = nameof(RelationshipsInUpdateSupermarketRequest.Cashiers); + _ = nameof(RelationshipsInSupermarketResponse.StoreManager); + _ = nameof(RelationshipsInSupermarketResponse.BackupStoreManager); + _ = nameof(RelationshipsInSupermarketResponse.Cashiers); + _ = nameof(SupermarketType); + + _ = nameof(AttributesInCreateStaffMemberRequest.Name); + _ = nameof(AttributesInCreateStaffMemberRequest.Age); + _ = nameof(AttributesInUpdateStaffMemberRequest.Name); + _ = nameof(AttributesInUpdateStaffMemberRequest.Age); + _ = nameof(AttributesInStaffMemberResponse.Name); + _ = nameof(AttributesInStaffMemberResponse.Age); + } + + [Fact] + public void Generated_relationship_container_types_are_named_as_expected() + { + _ = nameof(ToOneStaffMemberInRequest.Meta); + _ = nameof(ToOneStaffMemberInResponse.Meta); + _ = nameof(NullableToOneStaffMemberInRequest.Meta); + _ = nameof(NullableToOneStaffMemberInResponse.Meta); + _ = nameof(ToManyStaffMemberInRequest.Meta); + _ = nameof(ToManyStaffMemberInResponse.Meta); + + _ = nameof(SupermarketBackupStoreManagerRelationshipIdentifier); + _ = nameof(SupermarketCashiersRelationshipIdentifier); + _ = nameof(SupermarketStoreManagerRelationshipIdentifier); + } + + [Fact] + public void Generated_relationship_name_enums_are_named_as_expected() + { + _ = nameof(SupermarketBackupStoreManagerRelationshipName.BackupStoreManager); + _ = nameof(SupermarketCashiersRelationshipName.Cashiers); + _ = nameof(SupermarketStoreManagerRelationshipName.StoreManager); + } + + [Fact] + public void Generated_resource_type_enums_are_named_as_expected() + { + _ = nameof(SupermarketResourceType.Supermarkets); + _ = nameof(StaffMemberResourceType.StaffMembers); + _ = nameof(ResourceType.Supermarkets); + _ = nameof(ResourceType.StaffMembers); + } + + [Fact] + public void Generated_operation_type_enums_are_named_as_expected() + { + _ = nameof(AddOperationCode.Add); + _ = nameof(UpdateOperationCode.Update); + _ = nameof(RemoveOperationCode.Remove); + } + + [Fact] + public void Generated_data_types_are_named_as_expected() + { + _ = nameof(ResourceInCreateRequest.Meta); + _ = nameof(ResourceInUpdateRequest.Meta); + _ = nameof(IdentifierInRequest.Meta); + _ = nameof(ResourceInResponse.Meta); + + _ = nameof(DataInCreateSupermarketRequest.Meta); + _ = nameof(DataInUpdateSupermarketRequest.Meta); + _ = nameof(DataInSupermarketResponse.Meta); + + _ = nameof(SupermarketIdentifierInRequest.Meta); + + _ = nameof(DataInCreateStaffMemberRequest.Meta); + _ = nameof(DataInUpdateStaffMemberRequest.Meta); + _ = nameof(DataInStaffMemberResponse.Meta); + + _ = nameof(StaffMemberIdentifierInRequest.Meta); + _ = nameof(StaffMemberIdentifierInResponse.Meta); + } + + [Fact] + public void Generated_predefined_types_are_named_as_expected() + { + _ = nameof(Jsonapi.Meta); + _ = nameof(ErrorObject.Meta); + _ = nameof(ErrorSource); + _ = nameof(Meta); + + _ = nameof(AtomicOperation.Meta); + _ = nameof(AtomicResult.Meta); + } +} diff --git a/test/OpenApiNSwagClientTests/NamingConventions/KebabCase/GeneratedTypesTests.cs b/test/OpenApiNSwagClientTests/NamingConventions/KebabCase/GeneratedTypesTests.cs new file mode 100644 index 0000000000..ad58e822bd --- /dev/null +++ b/test/OpenApiNSwagClientTests/NamingConventions/KebabCase/GeneratedTypesTests.cs @@ -0,0 +1,203 @@ +using OpenApiNSwagClientTests.NamingConventions.KebabCase.GeneratedCode; +using Xunit; +using GeneratedClient = OpenApiNSwagClientTests.NamingConventions.KebabCase.GeneratedCode.KebabCaseClient; + +namespace OpenApiNSwagClientTests.NamingConventions.KebabCase; + +public sealed class GeneratedTypesTests +{ + [Fact] + public void Generated_endpoint_methods_are_named_as_expected() + { + _ = nameof(GeneratedClient.GetSupermarketCollectionAsync); + _ = nameof(GeneratedClient.HeadSupermarketCollectionAsync); + _ = nameof(GeneratedClient.PostSupermarketAsync); + _ = nameof(GeneratedClient.GetSupermarketAsync); + _ = nameof(GeneratedClient.HeadSupermarketAsync); + _ = nameof(GeneratedClient.PatchSupermarketAsync); + _ = nameof(GeneratedClient.DeleteSupermarketAsync); + _ = nameof(GeneratedClient.GetSupermarketBackupStoreManagerAsync); + _ = nameof(GeneratedClient.HeadSupermarketBackupStoreManagerAsync); + _ = nameof(GeneratedClient.GetSupermarketBackupStoreManagerRelationshipAsync); + _ = nameof(GeneratedClient.HeadSupermarketBackupStoreManagerRelationshipAsync); + _ = nameof(GeneratedClient.PatchSupermarketBackupStoreManagerRelationshipAsync); + _ = nameof(GeneratedClient.GetSupermarketCashiersAsync); + _ = nameof(GeneratedClient.HeadSupermarketCashiersAsync); + _ = nameof(GeneratedClient.GetSupermarketCashiersRelationshipAsync); + _ = nameof(GeneratedClient.HeadSupermarketCashiersRelationshipAsync); + _ = nameof(GeneratedClient.PostSupermarketCashiersRelationshipAsync); + _ = nameof(GeneratedClient.PatchSupermarketCashiersRelationshipAsync); + _ = nameof(GeneratedClient.DeleteSupermarketCashiersRelationshipAsync); + _ = nameof(GeneratedClient.GetSupermarketStoreManagerAsync); + _ = nameof(GeneratedClient.HeadSupermarketStoreManagerAsync); + _ = nameof(GeneratedClient.GetSupermarketStoreManagerRelationshipAsync); + _ = nameof(GeneratedClient.HeadSupermarketStoreManagerRelationshipAsync); + _ = nameof(GeneratedClient.PatchSupermarketStoreManagerRelationshipAsync); + + _ = nameof(GeneratedClient.GetStaffMemberCollectionAsync); + _ = nameof(GeneratedClient.HeadStaffMemberCollectionAsync); + _ = nameof(GeneratedClient.PostStaffMemberAsync); + _ = nameof(GeneratedClient.GetStaffMemberAsync); + _ = nameof(GeneratedClient.HeadStaffMemberAsync); + _ = nameof(GeneratedClient.PatchStaffMemberAsync); + _ = nameof(GeneratedClient.DeleteStaffMemberAsync); + + _ = nameof(GeneratedClient.PostOperationsAsync); + } + + [Fact] + public void Generated_top_level_document_types_are_named_as_expected() + { + _ = nameof(SupermarketCollectionResponseDocument.Meta); + _ = nameof(CreateSupermarketRequestDocument.Meta); + _ = nameof(PrimarySupermarketResponseDocument.Meta); + _ = nameof(UpdateSupermarketRequestDocument.Meta); + + _ = nameof(StaffMemberCollectionResponseDocument.Meta); + _ = nameof(CreateStaffMemberRequestDocument.Meta); + _ = nameof(PrimaryStaffMemberResponseDocument.Meta); + _ = nameof(UpdateStaffMemberRequestDocument.Meta); + _ = nameof(StaffMemberIdentifierCollectionResponseDocument.Meta); + _ = nameof(StaffMemberIdentifierResponseDocument.Meta); + _ = nameof(SecondaryStaffMemberResponseDocument.Meta); + _ = nameof(NullableSecondaryStaffMemberResponseDocument.Meta); + _ = nameof(NullableStaffMemberIdentifierResponseDocument.Meta); + + _ = nameof(ErrorResponseDocument.Meta); + + _ = nameof(OperationsRequestDocument.Meta); + _ = nameof(OperationsResponseDocument.Meta); + } + + [Fact] + public void Generated_link_types_are_named_as_expected() + { + _ = nameof(ResourceTopLevelLinks); + _ = nameof(ResourceCollectionTopLevelLinks); + _ = nameof(ResourceIdentifierTopLevelLinks); + _ = nameof(ResourceIdentifierCollectionTopLevelLinks); + _ = nameof(ErrorTopLevelLinks); + _ = nameof(ResourceLinks); + _ = nameof(RelationshipLinks); + _ = nameof(ErrorLinks); + } + + [Fact] + public void Generated_operation_types_are_named_as_expected() + { + _ = nameof(CreateSupermarketOperation.Meta); + _ = nameof(UpdateSupermarketOperation.Meta); + _ = nameof(DeleteSupermarketOperation.Meta); + _ = nameof(UpdateSupermarketBackupStoreManagerRelationshipOperation.Meta); + _ = nameof(UpdateSupermarketCashiersRelationshipOperation.Meta); + _ = nameof(AddToSupermarketCashiersRelationshipOperation.Meta); + _ = nameof(RemoveFromSupermarketCashiersRelationshipOperation.Meta); + _ = nameof(UpdateSupermarketStoreManagerRelationshipOperation.Meta); + + _ = nameof(CreateStaffMemberOperation.Meta); + _ = nameof(UpdateStaffMemberOperation.Meta); + _ = nameof(DeleteStaffMemberOperation.Meta); + } + + [Fact] + public void Generated_resource_field_types_are_named_as_expected() + { + _ = nameof(AttributesInCreateSupermarketRequest.NameOfCity); + _ = nameof(AttributesInCreateSupermarketRequest.Kind); + _ = nameof(AttributesInUpdateSupermarketRequest.NameOfCity); + _ = nameof(AttributesInUpdateSupermarketRequest.Kind); + _ = nameof(AttributesInSupermarketResponse.NameOfCity); + _ = nameof(AttributesInSupermarketResponse.Kind); + _ = nameof(RelationshipsInCreateSupermarketRequest.StoreManager); + _ = nameof(RelationshipsInCreateSupermarketRequest.BackupStoreManager); + _ = nameof(RelationshipsInCreateSupermarketRequest.Cashiers); + _ = nameof(RelationshipsInUpdateSupermarketRequest.StoreManager); + _ = nameof(RelationshipsInUpdateSupermarketRequest.BackupStoreManager); + _ = nameof(RelationshipsInUpdateSupermarketRequest.Cashiers); + _ = nameof(RelationshipsInSupermarketResponse.StoreManager); + _ = nameof(RelationshipsInSupermarketResponse.BackupStoreManager); + _ = nameof(RelationshipsInSupermarketResponse.Cashiers); + _ = nameof(SupermarketType); + + _ = nameof(AttributesInCreateStaffMemberRequest.Name); + _ = nameof(AttributesInCreateStaffMemberRequest.Age); + _ = nameof(AttributesInUpdateStaffMemberRequest.Name); + _ = nameof(AttributesInUpdateStaffMemberRequest.Age); + _ = nameof(AttributesInStaffMemberResponse.Name); + _ = nameof(AttributesInStaffMemberResponse.Age); + } + + [Fact] + public void Generated_relationship_container_types_are_named_as_expected() + { + _ = nameof(ToOneStaffMemberInRequest.Meta); + _ = nameof(ToOneStaffMemberInResponse.Meta); + _ = nameof(NullableToOneStaffMemberInRequest.Meta); + _ = nameof(NullableToOneStaffMemberInResponse.Meta); + _ = nameof(ToManyStaffMemberInRequest.Meta); + _ = nameof(ToManyStaffMemberInResponse.Meta); + + _ = nameof(SupermarketBackupStoreManagerRelationshipIdentifier); + _ = nameof(SupermarketCashiersRelationshipIdentifier); + _ = nameof(SupermarketStoreManagerRelationshipIdentifier); + } + + [Fact] + public void Generated_relationship_name_enums_are_named_as_expected() + { + _ = nameof(SupermarketBackupStoreManagerRelationshipName.BackupStoreManager); + _ = nameof(SupermarketCashiersRelationshipName.Cashiers); + _ = nameof(SupermarketStoreManagerRelationshipName.StoreManager); + } + + [Fact] + public void Generated_resource_type_enums_are_named_as_expected() + { + _ = nameof(SupermarketResourceType.Supermarkets); + _ = nameof(StaffMemberResourceType.StaffMembers); + _ = nameof(ResourceType.Supermarkets); + _ = nameof(ResourceType.StaffMembers); + } + + [Fact] + public void Generated_operation_type_enums_are_named_as_expected() + { + _ = nameof(AddOperationCode.Add); + _ = nameof(UpdateOperationCode.Update); + _ = nameof(RemoveOperationCode.Remove); + } + + [Fact] + public void Generated_data_types_are_named_as_expected() + { + _ = nameof(ResourceInCreateRequest.Meta); + _ = nameof(ResourceInUpdateRequest.Meta); + _ = nameof(IdentifierInRequest.Meta); + _ = nameof(ResourceInResponse.Meta); + + _ = nameof(DataInCreateSupermarketRequest.Meta); + _ = nameof(DataInUpdateSupermarketRequest.Meta); + _ = nameof(DataInSupermarketResponse.Meta); + + _ = nameof(SupermarketIdentifierInRequest.Meta); + + _ = nameof(DataInCreateStaffMemberRequest.Meta); + _ = nameof(DataInUpdateStaffMemberRequest.Meta); + _ = nameof(DataInStaffMemberResponse.Meta); + + _ = nameof(StaffMemberIdentifierInRequest.Meta); + _ = nameof(StaffMemberIdentifierInResponse.Meta); + } + + [Fact] + public void Generated_predefined_types_are_named_as_expected() + { + _ = nameof(Jsonapi.Meta); + _ = nameof(ErrorObject.Meta); + _ = nameof(ErrorSource); + _ = nameof(Meta); + + _ = nameof(AtomicOperation.Meta); + _ = nameof(AtomicResult.Meta); + } +} diff --git a/test/OpenApiNSwagClientTests/NamingConventions/PascalCase/GeneratedTypesTests.cs b/test/OpenApiNSwagClientTests/NamingConventions/PascalCase/GeneratedTypesTests.cs new file mode 100644 index 0000000000..916cd8d053 --- /dev/null +++ b/test/OpenApiNSwagClientTests/NamingConventions/PascalCase/GeneratedTypesTests.cs @@ -0,0 +1,203 @@ +using OpenApiNSwagClientTests.NamingConventions.PascalCase.GeneratedCode; +using Xunit; +using GeneratedClient = OpenApiNSwagClientTests.NamingConventions.PascalCase.GeneratedCode.PascalCaseClient; + +namespace OpenApiNSwagClientTests.NamingConventions.PascalCase; + +public sealed class GeneratedTypesTests +{ + [Fact] + public void Generated_endpoint_methods_are_named_as_expected() + { + _ = nameof(GeneratedClient.GetSupermarketCollectionAsync); + _ = nameof(GeneratedClient.HeadSupermarketCollectionAsync); + _ = nameof(GeneratedClient.PostSupermarketAsync); + _ = nameof(GeneratedClient.GetSupermarketAsync); + _ = nameof(GeneratedClient.HeadSupermarketAsync); + _ = nameof(GeneratedClient.PatchSupermarketAsync); + _ = nameof(GeneratedClient.DeleteSupermarketAsync); + _ = nameof(GeneratedClient.GetSupermarketBackupStoreManagerAsync); + _ = nameof(GeneratedClient.HeadSupermarketBackupStoreManagerAsync); + _ = nameof(GeneratedClient.GetSupermarketBackupStoreManagerRelationshipAsync); + _ = nameof(GeneratedClient.HeadSupermarketBackupStoreManagerRelationshipAsync); + _ = nameof(GeneratedClient.PatchSupermarketBackupStoreManagerRelationshipAsync); + _ = nameof(GeneratedClient.GetSupermarketCashiersAsync); + _ = nameof(GeneratedClient.HeadSupermarketCashiersAsync); + _ = nameof(GeneratedClient.GetSupermarketCashiersRelationshipAsync); + _ = nameof(GeneratedClient.HeadSupermarketCashiersRelationshipAsync); + _ = nameof(GeneratedClient.PostSupermarketCashiersRelationshipAsync); + _ = nameof(GeneratedClient.PatchSupermarketCashiersRelationshipAsync); + _ = nameof(GeneratedClient.DeleteSupermarketCashiersRelationshipAsync); + _ = nameof(GeneratedClient.GetSupermarketStoreManagerAsync); + _ = nameof(GeneratedClient.HeadSupermarketStoreManagerAsync); + _ = nameof(GeneratedClient.GetSupermarketStoreManagerRelationshipAsync); + _ = nameof(GeneratedClient.HeadSupermarketStoreManagerRelationshipAsync); + _ = nameof(GeneratedClient.PatchSupermarketStoreManagerRelationshipAsync); + + _ = nameof(GeneratedClient.GetStaffMemberCollectionAsync); + _ = nameof(GeneratedClient.HeadStaffMemberCollectionAsync); + _ = nameof(GeneratedClient.PostStaffMemberAsync); + _ = nameof(GeneratedClient.GetStaffMemberAsync); + _ = nameof(GeneratedClient.HeadStaffMemberAsync); + _ = nameof(GeneratedClient.PatchStaffMemberAsync); + _ = nameof(GeneratedClient.DeleteStaffMemberAsync); + + _ = nameof(GeneratedClient.PostOperationsAsync); + } + + [Fact] + public void Generated_top_level_document_types_are_named_as_expected() + { + _ = nameof(SupermarketCollectionResponseDocument.Meta); + _ = nameof(CreateSupermarketRequestDocument.Meta); + _ = nameof(PrimarySupermarketResponseDocument.Meta); + _ = nameof(UpdateSupermarketRequestDocument.Meta); + + _ = nameof(StaffMemberCollectionResponseDocument.Meta); + _ = nameof(CreateStaffMemberRequestDocument.Meta); + _ = nameof(PrimaryStaffMemberResponseDocument.Meta); + _ = nameof(UpdateStaffMemberRequestDocument.Meta); + _ = nameof(StaffMemberIdentifierCollectionResponseDocument.Meta); + _ = nameof(StaffMemberIdentifierResponseDocument.Meta); + _ = nameof(SecondaryStaffMemberResponseDocument.Meta); + _ = nameof(NullableSecondaryStaffMemberResponseDocument.Meta); + _ = nameof(NullableStaffMemberIdentifierResponseDocument.Meta); + + _ = nameof(ErrorResponseDocument.Meta); + + _ = nameof(OperationsRequestDocument.Meta); + _ = nameof(OperationsResponseDocument.Meta); + } + + [Fact] + public void Generated_link_types_are_named_as_expected() + { + _ = nameof(ResourceTopLevelLinks); + _ = nameof(ResourceCollectionTopLevelLinks); + _ = nameof(ResourceIdentifierTopLevelLinks); + _ = nameof(ResourceIdentifierCollectionTopLevelLinks); + _ = nameof(ErrorTopLevelLinks); + _ = nameof(ResourceLinks); + _ = nameof(RelationshipLinks); + _ = nameof(ErrorLinks); + } + + [Fact] + public void Generated_operation_types_are_named_as_expected() + { + _ = nameof(CreateSupermarketOperation.Meta); + _ = nameof(UpdateSupermarketOperation.Meta); + _ = nameof(DeleteSupermarketOperation.Meta); + _ = nameof(UpdateSupermarketBackupStoreManagerRelationshipOperation.Meta); + _ = nameof(UpdateSupermarketCashiersRelationshipOperation.Meta); + _ = nameof(AddToSupermarketCashiersRelationshipOperation.Meta); + _ = nameof(RemoveFromSupermarketCashiersRelationshipOperation.Meta); + _ = nameof(UpdateSupermarketStoreManagerRelationshipOperation.Meta); + + _ = nameof(CreateStaffMemberOperation.Meta); + _ = nameof(UpdateStaffMemberOperation.Meta); + _ = nameof(DeleteStaffMemberOperation.Meta); + } + + [Fact] + public void Generated_resource_field_types_are_named_as_expected() + { + _ = nameof(AttributesInCreateSupermarketRequest.NameOfCity); + _ = nameof(AttributesInCreateSupermarketRequest.Kind); + _ = nameof(AttributesInUpdateSupermarketRequest.NameOfCity); + _ = nameof(AttributesInUpdateSupermarketRequest.Kind); + _ = nameof(AttributesInSupermarketResponse.NameOfCity); + _ = nameof(AttributesInSupermarketResponse.Kind); + _ = nameof(RelationshipsInCreateSupermarketRequest.StoreManager); + _ = nameof(RelationshipsInCreateSupermarketRequest.BackupStoreManager); + _ = nameof(RelationshipsInCreateSupermarketRequest.Cashiers); + _ = nameof(RelationshipsInUpdateSupermarketRequest.StoreManager); + _ = nameof(RelationshipsInUpdateSupermarketRequest.BackupStoreManager); + _ = nameof(RelationshipsInUpdateSupermarketRequest.Cashiers); + _ = nameof(RelationshipsInSupermarketResponse.StoreManager); + _ = nameof(RelationshipsInSupermarketResponse.BackupStoreManager); + _ = nameof(RelationshipsInSupermarketResponse.Cashiers); + _ = nameof(SupermarketType); + + _ = nameof(AttributesInCreateStaffMemberRequest.Name); + _ = nameof(AttributesInCreateStaffMemberRequest.Age); + _ = nameof(AttributesInUpdateStaffMemberRequest.Name); + _ = nameof(AttributesInUpdateStaffMemberRequest.Age); + _ = nameof(AttributesInStaffMemberResponse.Name); + _ = nameof(AttributesInStaffMemberResponse.Age); + } + + [Fact] + public void Generated_relationship_container_types_are_named_as_expected() + { + _ = nameof(ToOneStaffMemberInRequest.Meta); + _ = nameof(ToOneStaffMemberInResponse.Meta); + _ = nameof(NullableToOneStaffMemberInRequest.Meta); + _ = nameof(NullableToOneStaffMemberInResponse.Meta); + _ = nameof(ToManyStaffMemberInRequest.Meta); + _ = nameof(ToManyStaffMemberInResponse.Meta); + + _ = nameof(SupermarketBackupStoreManagerRelationshipIdentifier); + _ = nameof(SupermarketCashiersRelationshipIdentifier); + _ = nameof(SupermarketStoreManagerRelationshipIdentifier); + } + + [Fact] + public void Generated_relationship_name_enums_are_named_as_expected() + { + _ = nameof(SupermarketBackupStoreManagerRelationshipName.BackupStoreManager); + _ = nameof(SupermarketCashiersRelationshipName.Cashiers); + _ = nameof(SupermarketStoreManagerRelationshipName.StoreManager); + } + + [Fact] + public void Generated_resource_type_enums_are_named_as_expected() + { + _ = nameof(SupermarketResourceType.Supermarkets); + _ = nameof(StaffMemberResourceType.StaffMembers); + _ = nameof(ResourceType.Supermarkets); + _ = nameof(ResourceType.StaffMembers); + } + + [Fact] + public void Generated_operation_type_enums_are_named_as_expected() + { + _ = nameof(AddOperationCode.Add); + _ = nameof(UpdateOperationCode.Update); + _ = nameof(RemoveOperationCode.Remove); + } + + [Fact] + public void Generated_data_types_are_named_as_expected() + { + _ = nameof(ResourceInCreateRequest.Meta); + _ = nameof(ResourceInUpdateRequest.Meta); + _ = nameof(IdentifierInRequest.Meta); + _ = nameof(ResourceInResponse.Meta); + + _ = nameof(DataInCreateSupermarketRequest.Meta); + _ = nameof(DataInUpdateSupermarketRequest.Meta); + _ = nameof(DataInSupermarketResponse.Meta); + + _ = nameof(SupermarketIdentifierInRequest.Meta); + + _ = nameof(DataInCreateStaffMemberRequest.Meta); + _ = nameof(DataInUpdateStaffMemberRequest.Meta); + _ = nameof(DataInStaffMemberResponse.Meta); + + _ = nameof(StaffMemberIdentifierInRequest.Meta); + _ = nameof(StaffMemberIdentifierInResponse.Meta); + } + + [Fact] + public void Generated_predefined_types_are_named_as_expected() + { + _ = nameof(Jsonapi.Meta); + _ = nameof(ErrorObject.Meta); + _ = nameof(ErrorSource); + _ = nameof(Meta); + + _ = nameof(AtomicOperation.Meta); + _ = nameof(AtomicResult.Meta); + } +} diff --git a/test/OpenApiNSwagClientTests/ObjectExtensions.cs b/test/OpenApiNSwagClientTests/ObjectExtensions.cs new file mode 100644 index 0000000000..6be27b4e3b --- /dev/null +++ b/test/OpenApiNSwagClientTests/ObjectExtensions.cs @@ -0,0 +1,36 @@ +using System.Reflection; + +namespace OpenApiNSwagClientTests; + +internal static class ObjectExtensions +{ + public static object? GetPropertyValue(this object source, string propertyName) + { + ArgumentNullException.ThrowIfNull(source); + ArgumentNullException.ThrowIfNull(propertyName); + + PropertyInfo propertyInfo = GetExistingProperty(source.GetType(), propertyName); + return propertyInfo.GetValue(source); + } + + public static void SetPropertyValue(this object source, string propertyName, object? value) + { + ArgumentNullException.ThrowIfNull(source); + ArgumentNullException.ThrowIfNull(propertyName); + + PropertyInfo propertyInfo = GetExistingProperty(source.GetType(), propertyName); + propertyInfo.SetValue(source, value); + } + + private static PropertyInfo GetExistingProperty(Type type, string propertyName) + { + PropertyInfo? propertyInfo = type.GetProperty(propertyName); + + if (propertyInfo == null) + { + throw new InvalidOperationException($"Type '{type}' does not contain a property named '{propertyName}'."); + } + + return propertyInfo; + } +} diff --git a/test/OpenApiNSwagClientTests/OpenApiNSwagClientTests.csproj b/test/OpenApiNSwagClientTests/OpenApiNSwagClientTests.csproj new file mode 100644 index 0000000000..35a6ae73ff --- /dev/null +++ b/test/OpenApiNSwagClientTests/OpenApiNSwagClientTests.csproj @@ -0,0 +1,94 @@ + + + + net9.0 + + + + + + + + + + + + + + + + + + + + + + + internal + + + + + $(MSBuildProjectName).LegacyOpenApi.GeneratedCode + LegacyClient + %(ClassName).cs + false + false + false + + + KebabCase + $(MSBuildProjectName).NamingConventions.%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs + + + CamelCase + $(MSBuildProjectName).NamingConventions.%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs + + + PascalCase + $(MSBuildProjectName).NamingConventions.%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs + + + NrtOffMsvOff + $(MSBuildProjectName).ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOff.GeneratedCode + %(Name)Client + %(ClassName).cs + false + false + false + + + NrtOffMsvOn + $(MSBuildProjectName).ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOn.GeneratedCode + %(Name)Client + %(ClassName).cs + false + false + false + + + NrtOnMsvOff + $(MSBuildProjectName).ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOff.GeneratedCode + %(Name)Client + %(ClassName).cs + true + false + false + + + NrtOnMsvOn + $(MSBuildProjectName).ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOn.GeneratedCode + %(Name)Client + %(ClassName).cs + true + false + false + + + diff --git a/test/OpenApiNSwagClientTests/PropertyInfoAssertionsExtensions.cs b/test/OpenApiNSwagClientTests/PropertyInfoAssertionsExtensions.cs new file mode 100644 index 0000000000..bb0ff8dbd1 --- /dev/null +++ b/test/OpenApiNSwagClientTests/PropertyInfoAssertionsExtensions.cs @@ -0,0 +1,20 @@ +using System.Reflection; +using FluentAssertions; +using FluentAssertions.Types; + +namespace OpenApiNSwagClientTests; + +internal static class PropertyInfoAssertionsExtensions +{ + [CustomAssertion] + public static void HaveNullabilityState(this PropertyInfoAssertions source, NullabilityState expected, string because = "", params object[] becauseArgs) + { + PropertyInfo propertyInfo = source.Subject; + + NullabilityInfoContext nullabilityContext = new(); + NullabilityInfo nullabilityInfo = nullabilityContext.Create(propertyInfo); + + nullabilityInfo.ReadState.Should().Be(expected, because, becauseArgs); + nullabilityInfo.WriteState.Should().Be(expected, because, becauseArgs); + } +} diff --git a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/CreateResourceTests.cs b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/CreateResourceTests.cs new file mode 100644 index 0000000000..3e09f3b68f --- /dev/null +++ b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/CreateResourceTests.cs @@ -0,0 +1,252 @@ +using System.Net; +using System.Text.Json; +using FluentAssertions; +using FluentAssertions.Specialized; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using Newtonsoft.Json; +using OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOff.GeneratedCode; +using TestBuildingBlocks; +using Xunit; + +namespace OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOff; + +public sealed class CreateResourceTests : BaseOpenApiNSwagClientTests +{ + private readonly NrtOffMsvOffFakers _fakers = new(); + + [Theory] + [InlineData(nameof(AttributesInCreateResourceRequest.ReferenceType), "referenceType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredReferenceType), "requiredReferenceType")] + [InlineData(nameof(AttributesInCreateResourceRequest.ValueType), "valueType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredValueType), "requiredValueType")] + [InlineData(nameof(AttributesInCreateResourceRequest.NullableValueType), "nullableValueType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNullableValueType), "requiredNullableValueType")] + public async Task Can_set_attribute_to_default_value(string attributePropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + ToOne = _fakers.NullableToOne.GenerateOne(), + RequiredToOne = _fakers.NullableToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOffMsvOffClient(wrapper.HttpClient); + + object? defaultValue = SetPropertyToDefaultValue(requestBody.Data.Attributes, attributePropertyName); + apiClient.MarkAsTracked(requestBody.Data.Attributes, attributePropertyName); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PostResourceAsync(null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath("data.attributes").With(attributesObject => + { + attributesObject.Should().ContainPath(jsonPropertyName).With(attribute => attribute.Should().Be(defaultValue)); + }); + } + + [Theory] + [InlineData(nameof(AttributesInCreateResourceRequest.ReferenceType), "referenceType")] + [InlineData(nameof(AttributesInCreateResourceRequest.ValueType), "valueType")] + [InlineData(nameof(AttributesInCreateResourceRequest.NullableValueType), "nullableValueType")] + public async Task Can_omit_attribute(string attributePropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + ToOne = _fakers.NullableToOne.GenerateOne(), + RequiredToOne = _fakers.NullableToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOffMsvOffClient(wrapper.HttpClient); + + SetPropertyToInitialValue(requestBody.Data.Attributes, attributePropertyName); + apiClient.MarkAsTracked(requestBody.Data.Attributes); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PostResourceAsync(null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath("data.attributes").With(attributesObject => + { + attributesObject.Should().NotContainPath(jsonPropertyName); + }); + } + + [Theory] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredReferenceType), "requiredReferenceType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredValueType), "requiredValueType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNullableValueType), "requiredNullableValueType")] + public async Task Cannot_omit_attribute(string attributePropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + ToOne = _fakers.NullableToOne.GenerateOne(), + RequiredToOne = _fakers.NullableToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOffMsvOffClient(wrapper.HttpClient); + + SetPropertyToInitialValue(requestBody.Data.Attributes, attributePropertyName); + apiClient.MarkAsTracked(requestBody.Data.Attributes); + + // Act + Func action = async () => await apiClient.PostResourceAsync(null, requestBody); + + // Assert + ExceptionAssertions assertion = await action.Should().ThrowExactlyAsync(); + + assertion.Which.Message.Should().Be( + $"Cannot write a default value for property '{jsonPropertyName}'. Property requires a non-default value. Path 'data.attributes'."); + } + + [Theory] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.ToOne), "toOne")] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.RequiredToOne), "requiredToOne")] + public async Task Can_clear_relationship(string relationshipPropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + ToOne = _fakers.NullableToOne.GenerateOne(), + RequiredToOne = _fakers.NullableToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOffMsvOffClient(wrapper.HttpClient); + + SetDataPropertyToNull(requestBody.Data.Relationships, relationshipPropertyName); + apiClient.MarkAsTracked(requestBody.Data.Relationships, relationshipPropertyName); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PostResourceAsync(null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath($"data.relationships.{jsonPropertyName}.data").With(relationshipDataObject => + { + relationshipDataObject.ValueKind.Should().Be(JsonValueKind.Null); + }); + } + + [Theory] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.ToMany), "toMany")] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.RequiredToMany), "requiredToMany")] + public async Task Cannot_clear_relationship(string relationshipPropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + ToOne = _fakers.NullableToOne.GenerateOne(), + RequiredToOne = _fakers.NullableToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOffMsvOffClient(wrapper.HttpClient); + + SetDataPropertyToNull(requestBody.Data.Relationships, relationshipPropertyName); + apiClient.MarkAsTracked(requestBody.Data.Relationships, relationshipPropertyName); + + // Act + Func action = async () => await apiClient.PostResourceAsync(null, requestBody); + + // Assert + ExceptionAssertions assertion = await action.Should().ThrowExactlyAsync(); + + assertion.Which.Message.Should().Be( + $"Cannot write a null value for property 'data'. Property requires a value. Path 'data.relationships.{jsonPropertyName}'."); + } + + [Theory] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.ToOne), "toOne")] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.ToMany), "toMany")] + public async Task Can_omit_relationship(string relationshipPropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + ToOne = _fakers.NullableToOne.GenerateOne(), + RequiredToOne = _fakers.NullableToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOffMsvOffClient(wrapper.HttpClient); + + SetPropertyToInitialValue(requestBody.Data.Relationships, relationshipPropertyName); + apiClient.MarkAsTracked(requestBody.Data.Relationships); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PostResourceAsync(null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath("data.relationships").With(relationshipsObject => + { + relationshipsObject.Should().NotContainPath(jsonPropertyName); + }); + } +} diff --git a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/NrtOffMsvOffFakers.cs b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/NrtOffMsvOffFakers.cs new file mode 100644 index 0000000000..b32063bade --- /dev/null +++ b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/NrtOffMsvOffFakers.cs @@ -0,0 +1,23 @@ +using Bogus; +using OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOff.GeneratedCode; + +namespace OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOff; + +internal sealed class NrtOffMsvOffFakers +{ + private readonly Lazy> _lazyPostAttributesFaker = + new(FakerFactory.Instance.Create); + + private readonly Lazy> _lazyPatchAttributesFaker = + new(FakerFactory.Instance.Create); + + private readonly Lazy> _lazyNullableToOneFaker = + new(FakerFactory.Instance.CreateForObjectWithResourceId); + + private readonly Lazy> _lazyToManyFaker = new(FakerFactory.Instance.CreateForObjectWithResourceId); + + public Faker PostAttributes => _lazyPostAttributesFaker.Value; + public Faker PatchAttributes => _lazyPatchAttributesFaker.Value; + public Faker NullableToOne => _lazyNullableToOneFaker.Value; + public Faker ToMany => _lazyToManyFaker.Value; +} diff --git a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/NullabilityTests.cs b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/NullabilityTests.cs new file mode 100644 index 0000000000..ff3b027b89 --- /dev/null +++ b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/NullabilityTests.cs @@ -0,0 +1,44 @@ +using System.Reflection; +using FluentAssertions; +using OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOff.GeneratedCode; +using Xunit; + +namespace OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOff; + +public sealed class NullabilityTests +{ + [Theory] + [InlineData(nameof(AttributesInCreateResourceRequest.ReferenceType), NullabilityState.Unknown)] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredReferenceType), NullabilityState.Unknown)] + [InlineData(nameof(AttributesInCreateResourceRequest.ValueType), NullabilityState.NotNull)] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredValueType), NullabilityState.NotNull)] + [InlineData(nameof(AttributesInCreateResourceRequest.NullableValueType), NullabilityState.Nullable)] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNullableValueType), NullabilityState.Nullable)] + public void Nullability_of_generated_attribute_property_is_as_expected(string propertyName, NullabilityState expectedState) + { + // Act + PropertyInfo? property = typeof(AttributesInCreateResourceRequest).GetProperty(propertyName); + + // Assert + property.Should().NotBeNull(); + property.Should().HaveNullabilityState(expectedState); + } + + [Theory] + [InlineData(nameof(RelationshipsInCreateResourceRequest.ToOne), NullabilityState.Unknown)] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredToOne), NullabilityState.Unknown)] + [InlineData(nameof(RelationshipsInCreateResourceRequest.ToMany), NullabilityState.Unknown)] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredToMany), NullabilityState.Unknown)] + public void Nullability_of_generated_relationship_property_is_as_expected(string propertyName, NullabilityState expectedState) + { + // Act + PropertyInfo? relationshipProperty = typeof(RelationshipsInCreateResourceRequest).GetProperty(propertyName); + + // Assert + relationshipProperty.Should().NotBeNull(); + + PropertyInfo? dataProperty = relationshipProperty.PropertyType.GetProperty("Data"); + dataProperty.Should().NotBeNull(); + dataProperty.Should().HaveNullabilityState(expectedState); + } +} diff --git a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/UpdateResourceTests.cs b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/UpdateResourceTests.cs new file mode 100644 index 0000000000..ca5872c801 --- /dev/null +++ b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/UpdateResourceTests.cs @@ -0,0 +1,133 @@ +using System.Net; +using System.Text.Json; +using FluentAssertions; +using FluentAssertions.Specialized; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using Newtonsoft.Json; +using OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOff.GeneratedCode; +using TestBuildingBlocks; +using Xunit; + +namespace OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOff; + +public sealed class UpdateResourceTests : BaseOpenApiNSwagClientTests +{ + private readonly NrtOffMsvOffFakers _fakers = new(); + + [Fact] + public async Task Cannot_omit_Id() + { + // Arrange + var requestBody = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Attributes = _fakers.PatchAttributes.GenerateOne(), + Relationships = new RelationshipsInUpdateResourceRequest + { + ToOne = _fakers.NullableToOne.GenerateOne(), + RequiredToOne = _fakers.NullableToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOffMsvOffClient(wrapper.HttpClient); + + // Act + Func action = async () => await apiClient.PatchResourceAsync(Unknown.StringId.Int32, null, requestBody); + + // Assert + ExceptionAssertions assertion = await action.Should().ThrowExactlyAsync(); + + assertion.Which.Message.Should().Be("Cannot write a null value for property 'id'. Property requires a value. Path 'data'."); + } + + [Theory] + [InlineData(nameof(AttributesInUpdateResourceRequest.ReferenceType), "referenceType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.RequiredReferenceType), "requiredReferenceType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.ValueType), "valueType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.RequiredValueType), "requiredValueType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.NullableValueType), "nullableValueType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.RequiredNullableValueType), "requiredNullableValueType")] + public async Task Can_omit_attribute(string attributePropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Id = Unknown.StringId.Int32, + Attributes = _fakers.PatchAttributes.GenerateOne(), + Relationships = new RelationshipsInUpdateResourceRequest + { + ToOne = _fakers.NullableToOne.GenerateOne(), + RequiredToOne = _fakers.NullableToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOffMsvOffClient(wrapper.HttpClient); + + SetPropertyToInitialValue(requestBody.Data.Attributes, attributePropertyName); + apiClient.MarkAsTracked(requestBody.Data.Attributes); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(requestBody.Data.Id, null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath("data.attributes").With(attributesObject => + { + attributesObject.Should().NotContainPath(jsonPropertyName); + }); + } + + [Theory] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.ToOne), "toOne")] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.RequiredToOne), "requiredToOne")] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.ToMany), "toMany")] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.RequiredToMany), "requiredToMany")] + public async Task Can_omit_relationship(string relationshipPropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Id = Unknown.StringId.Int32, + Attributes = _fakers.PatchAttributes.GenerateOne(), + Relationships = new RelationshipsInUpdateResourceRequest + { + ToOne = _fakers.NullableToOne.GenerateOne(), + RequiredToOne = _fakers.NullableToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOffMsvOffClient(wrapper.HttpClient); + + SetPropertyToInitialValue(requestBody.Data.Relationships, relationshipPropertyName); + apiClient.MarkAsTracked(requestBody.Data.Relationships); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(requestBody.Data.Id, null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath("data.relationships").With(relationshipsObject => + { + relationshipsObject.Should().NotContainPath(jsonPropertyName); + }); + } +} diff --git a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/CreateResourceTests.cs b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/CreateResourceTests.cs new file mode 100644 index 0000000000..a1ca9ccc1f --- /dev/null +++ b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/CreateResourceTests.cs @@ -0,0 +1,323 @@ +using System.Net; +using System.Text.Json; +using FluentAssertions; +using FluentAssertions.Specialized; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using Newtonsoft.Json; +using OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOn.GeneratedCode; +using TestBuildingBlocks; +using Xunit; + +namespace OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOn; + +public sealed class CreateResourceTests : BaseOpenApiNSwagClientTests +{ + private readonly NrtOffMsvOnFakers _fakers = new(); + + [Theory] + [InlineData(nameof(AttributesInCreateResourceRequest.ReferenceType), "referenceType")] + [InlineData(nameof(AttributesInCreateResourceRequest.ValueType), "valueType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredValueType), "requiredValueType")] + [InlineData(nameof(AttributesInCreateResourceRequest.NullableValueType), "nullableValueType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNullableValueType), "requiredNullableValueType")] + public async Task Can_set_attribute_to_default_value(string attributePropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + ToOne = _fakers.NullableToOne.GenerateOne(), + RequiredToOne = _fakers.ToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOffMsvOnClient(wrapper.HttpClient); + + object? defaultValue = SetPropertyToDefaultValue(requestBody.Data.Attributes, attributePropertyName); + apiClient.MarkAsTracked(requestBody.Data.Attributes, attributePropertyName); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PostResourceAsync(null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath("data.attributes").With(attributesObject => + { + attributesObject.Should().ContainPath(jsonPropertyName).With(attribute => attribute.Should().Be(defaultValue)); + }); + } + + [Theory] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredReferenceType), "requiredReferenceType")] + public async Task Cannot_set_attribute_to_default_value(string attributePropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + ToOne = _fakers.NullableToOne.GenerateOne(), + RequiredToOne = _fakers.ToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOffMsvOnClient(wrapper.HttpClient); + + SetPropertyToDefaultValue(requestBody.Data.Attributes, attributePropertyName); + apiClient.MarkAsTracked(requestBody.Data.Attributes, attributePropertyName); + + // Act + Func action = async () => await apiClient.PostResourceAsync(null, requestBody); + + // Assert + ExceptionAssertions assertion = await action.Should().ThrowExactlyAsync(); + + assertion.Which.Message.Should().Be($"Cannot write a null value for property '{jsonPropertyName}'. Property requires a value. Path 'data.attributes'."); + } + + [Theory] + [InlineData(nameof(AttributesInCreateResourceRequest.ReferenceType), "referenceType")] + [InlineData(nameof(AttributesInCreateResourceRequest.ValueType), "valueType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredValueType), "requiredValueType")] + [InlineData(nameof(AttributesInCreateResourceRequest.NullableValueType), "nullableValueType")] + public async Task Can_omit_attribute(string attributePropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + ToOne = _fakers.NullableToOne.GenerateOne(), + RequiredToOne = _fakers.ToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOffMsvOnClient(wrapper.HttpClient); + + SetPropertyToInitialValue(requestBody.Data.Attributes, attributePropertyName); + apiClient.MarkAsTracked(requestBody.Data.Attributes); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PostResourceAsync(null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath("data.attributes").With(attributesObject => + { + attributesObject.Should().NotContainPath(jsonPropertyName); + }); + } + + [Theory] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredReferenceType), "requiredReferenceType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNullableValueType), "requiredNullableValueType")] + public async Task Cannot_omit_attribute(string attributePropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + ToOne = _fakers.NullableToOne.GenerateOne(), + RequiredToOne = _fakers.ToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOffMsvOnClient(wrapper.HttpClient); + + SetPropertyToInitialValue(requestBody.Data.Attributes, attributePropertyName); + apiClient.MarkAsTracked(requestBody.Data.Attributes); + + // Act + Func action = async () => await apiClient.PostResourceAsync(null, requestBody); + + // Assert + ExceptionAssertions assertion = await action.Should().ThrowExactlyAsync(); + + assertion.Which.Message.Should().Be( + $"Cannot write a default value for property '{jsonPropertyName}'. Property requires a non-default value. Path 'data.attributes'."); + } + + [Theory] + [InlineData(nameof(RelationshipsInCreateResourceRequest.ToOne), "toOne")] + public async Task Can_clear_relationship(string relationshipPropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + ToOne = _fakers.NullableToOne.GenerateOne(), + RequiredToOne = _fakers.ToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOffMsvOnClient(wrapper.HttpClient); + + SetDataPropertyToNull(requestBody.Data.Relationships, relationshipPropertyName); + apiClient.MarkAsTracked(requestBody.Data.Relationships, relationshipPropertyName); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PostResourceAsync(null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath($"data.relationships.{jsonPropertyName}.data").With(relationshipDataObject => + { + relationshipDataObject.ValueKind.Should().Be(JsonValueKind.Null); + }); + } + + [Theory] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredToOne), "requiredToOne")] + [InlineData(nameof(RelationshipsInCreateResourceRequest.ToMany), "toMany")] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredToMany), "requiredToMany")] + public async Task Cannot_clear_relationship(string relationshipPropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + ToOne = _fakers.NullableToOne.GenerateOne(), + RequiredToOne = _fakers.ToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOffMsvOnClient(wrapper.HttpClient); + + SetDataPropertyToNull(requestBody.Data.Relationships, relationshipPropertyName); + apiClient.MarkAsTracked(requestBody.Data.Relationships, relationshipPropertyName); + + // Act + Func action = async () => await apiClient.PostResourceAsync(null, requestBody); + + // Assert + ExceptionAssertions assertion = await action.Should().ThrowExactlyAsync(); + + assertion.Which.Message.Should().Be( + $"Cannot write a null value for property 'data'. Property requires a value. Path 'data.relationships.{jsonPropertyName}'."); + } + + [Theory] + [InlineData(nameof(RelationshipsInCreateResourceRequest.ToOne), "toOne")] + [InlineData(nameof(RelationshipsInCreateResourceRequest.ToMany), "toMany")] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredToMany), "requiredToMany")] + public async Task Can_omit_relationship(string relationshipPropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + ToOne = _fakers.NullableToOne.GenerateOne(), + RequiredToOne = _fakers.ToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOffMsvOnClient(wrapper.HttpClient); + + SetPropertyToInitialValue(requestBody.Data.Relationships, relationshipPropertyName); + apiClient.MarkAsTracked(requestBody.Data.Relationships); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PostResourceAsync(null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath("data.relationships").With(relationshipsObject => + { + relationshipsObject.Should().NotContainPath(jsonPropertyName); + }); + } + + [Theory] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredToOne), "requiredToOne")] + public async Task Cannot_omit_relationship(string relationshipPropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + ToOne = _fakers.NullableToOne.GenerateOne(), + RequiredToOne = _fakers.ToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOffMsvOnClient(wrapper.HttpClient); + + SetPropertyToInitialValue(requestBody.Data.Relationships, relationshipPropertyName); + apiClient.MarkAsTracked(requestBody.Data.Relationships); + + // Act + Func action = async () => await apiClient.PostResourceAsync(null, requestBody); + + // Assert + ExceptionAssertions assertion = await action.Should().ThrowExactlyAsync(); + + assertion.Which.Message.Should().Be( + $"Cannot write a null value for property 'id'. Property requires a value. Path 'data.relationships.{jsonPropertyName}.data'."); + } +} diff --git a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/NrtOffMsvOnFakers.cs b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/NrtOffMsvOnFakers.cs new file mode 100644 index 0000000000..8ffc94f6a9 --- /dev/null +++ b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/NrtOffMsvOnFakers.cs @@ -0,0 +1,26 @@ +using Bogus; +using OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOn.GeneratedCode; + +namespace OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOn; + +internal sealed class NrtOffMsvOnFakers +{ + private readonly Lazy> _lazyPostAttributesFaker = + new(FakerFactory.Instance.Create); + + private readonly Lazy> _lazyPatchAttributesFaker = + new(FakerFactory.Instance.Create); + + private readonly Lazy> _lazyToOneFaker = new(FakerFactory.Instance.CreateForObjectWithResourceId); + + private readonly Lazy> _lazyNullableToOneFaker = + new(FakerFactory.Instance.CreateForObjectWithResourceId); + + private readonly Lazy> _lazyToManyFaker = new(FakerFactory.Instance.CreateForObjectWithResourceId); + + public Faker PostAttributes => _lazyPostAttributesFaker.Value; + public Faker PatchAttributes => _lazyPatchAttributesFaker.Value; + public Faker ToOne => _lazyToOneFaker.Value; + public Faker NullableToOne => _lazyNullableToOneFaker.Value; + public Faker ToMany => _lazyToManyFaker.Value; +} diff --git a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/NullabilityTests.cs b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/NullabilityTests.cs new file mode 100644 index 0000000000..e6274f85b1 --- /dev/null +++ b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/NullabilityTests.cs @@ -0,0 +1,44 @@ +using System.Reflection; +using FluentAssertions; +using OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOn.GeneratedCode; +using Xunit; + +namespace OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOn; + +public sealed class NullabilityTests +{ + [Theory] + [InlineData(nameof(AttributesInCreateResourceRequest.ReferenceType), NullabilityState.Unknown)] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredReferenceType), NullabilityState.Unknown)] + [InlineData(nameof(AttributesInCreateResourceRequest.ValueType), NullabilityState.NotNull)] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredValueType), NullabilityState.NotNull)] + [InlineData(nameof(AttributesInCreateResourceRequest.NullableValueType), NullabilityState.Nullable)] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNullableValueType), NullabilityState.NotNull)] + public void Nullability_of_generated_attribute_property_is_as_expected(string propertyName, NullabilityState expectedState) + { + // Act + PropertyInfo? property = typeof(AttributesInCreateResourceRequest).GetProperty(propertyName); + + // Assert + property.Should().NotBeNull(); + property.Should().HaveNullabilityState(expectedState); + } + + [Theory] + [InlineData(nameof(RelationshipsInCreateResourceRequest.ToOne), NullabilityState.Unknown)] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredToOne), NullabilityState.Unknown)] + [InlineData(nameof(RelationshipsInCreateResourceRequest.ToMany), NullabilityState.Unknown)] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredToMany), NullabilityState.Unknown)] + public void Nullability_of_generated_relationship_property_is_as_expected(string propertyName, NullabilityState expectedState) + { + // Act + PropertyInfo? relationshipProperty = typeof(RelationshipsInCreateResourceRequest).GetProperty(propertyName); + + // Assert + relationshipProperty.Should().NotBeNull(); + + PropertyInfo? dataProperty = relationshipProperty.PropertyType.GetProperty("Data"); + dataProperty.Should().NotBeNull(); + dataProperty.Should().HaveNullabilityState(expectedState); + } +} diff --git a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/UpdateResourceTests.cs b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/UpdateResourceTests.cs new file mode 100644 index 0000000000..d92d2ca6a9 --- /dev/null +++ b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/UpdateResourceTests.cs @@ -0,0 +1,133 @@ +using System.Net; +using System.Text.Json; +using FluentAssertions; +using FluentAssertions.Specialized; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using Newtonsoft.Json; +using OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOn.GeneratedCode; +using TestBuildingBlocks; +using Xunit; + +namespace OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOn; + +public sealed class UpdateResourceTests : BaseOpenApiNSwagClientTests +{ + private readonly NrtOffMsvOnFakers _fakers = new(); + + [Fact] + public async Task Cannot_omit_Id() + { + // Arrange + var requestBody = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Attributes = _fakers.PatchAttributes.GenerateOne(), + Relationships = new RelationshipsInUpdateResourceRequest + { + ToOne = _fakers.NullableToOne.GenerateOne(), + RequiredToOne = _fakers.ToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOffMsvOnClient(wrapper.HttpClient); + + // Act + Func action = async () => await apiClient.PatchResourceAsync(Unknown.StringId.Int32, null, requestBody); + + // Assert + ExceptionAssertions assertion = await action.Should().ThrowExactlyAsync(); + + assertion.Which.Message.Should().Be("Cannot write a null value for property 'id'. Property requires a value. Path 'data'."); + } + + [Theory] + [InlineData(nameof(AttributesInUpdateResourceRequest.ReferenceType), "referenceType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.RequiredReferenceType), "requiredReferenceType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.ValueType), "valueType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.RequiredValueType), "requiredValueType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.NullableValueType), "nullableValueType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.RequiredNullableValueType), "requiredNullableValueType")] + public async Task Can_omit_attribute(string attributePropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Id = Unknown.StringId.Int32, + Attributes = _fakers.PatchAttributes.GenerateOne(), + Relationships = new RelationshipsInUpdateResourceRequest + { + ToOne = _fakers.NullableToOne.GenerateOne(), + RequiredToOne = _fakers.ToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOffMsvOnClient(wrapper.HttpClient); + + SetPropertyToInitialValue(requestBody.Data.Attributes, attributePropertyName); + apiClient.MarkAsTracked(requestBody.Data.Attributes); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(requestBody.Data.Id, null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath("data.attributes").With(attributesObject => + { + attributesObject.Should().NotContainPath(jsonPropertyName); + }); + } + + [Theory] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.ToOne), "toOne")] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.RequiredToOne), "requiredToOne")] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.ToMany), "toMany")] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.RequiredToMany), "requiredToMany")] + public async Task Can_omit_relationship(string relationshipPropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Id = Unknown.StringId.Int32, + Attributes = _fakers.PatchAttributes.GenerateOne(), + Relationships = new RelationshipsInUpdateResourceRequest + { + ToOne = _fakers.NullableToOne.GenerateOne(), + RequiredToOne = _fakers.ToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOffMsvOnClient(wrapper.HttpClient); + + SetPropertyToInitialValue(requestBody.Data.Relationships, relationshipPropertyName); + apiClient.MarkAsTracked(requestBody.Data.Relationships); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(requestBody.Data.Id, null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath("data.relationships").With(relationshipsObject => + { + relationshipsObject.Should().NotContainPath(jsonPropertyName); + }); + } +} diff --git a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/CreateResourceTests.cs b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/CreateResourceTests.cs new file mode 100644 index 0000000000..d59bb1ba97 --- /dev/null +++ b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/CreateResourceTests.cs @@ -0,0 +1,346 @@ +using System.Net; +using System.Text.Json; +using FluentAssertions; +using FluentAssertions.Specialized; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using Newtonsoft.Json; +using OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOff.GeneratedCode; +using TestBuildingBlocks; +using Xunit; + +namespace OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOff; + +public sealed class CreateResourceTests : BaseOpenApiNSwagClientTests +{ + private readonly NrtOnMsvOffFakers _fakers = new(); + + [Theory] + [InlineData(nameof(AttributesInCreateResourceRequest.NullableReferenceType), "nullableReferenceType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNullableReferenceType), "requiredNullableReferenceType")] + [InlineData(nameof(AttributesInCreateResourceRequest.ValueType), "valueType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredValueType), "requiredValueType")] + [InlineData(nameof(AttributesInCreateResourceRequest.NullableValueType), "nullableValueType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNullableValueType), "requiredNullableValueType")] + public async Task Can_set_attribute_to_default_value(string attributePropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + NonNullableToOne = _fakers.ToOne.GenerateOne(), + RequiredNonNullableToOne = _fakers.ToOne.GenerateOne(), + NullableToOne = _fakers.NullableToOne.GenerateOne(), + RequiredNullableToOne = _fakers.NullableToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOffClient(wrapper.HttpClient); + + object? defaultValue = SetPropertyToDefaultValue(requestBody.Data.Attributes, attributePropertyName); + apiClient.MarkAsTracked(requestBody.Data.Attributes, attributePropertyName); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PostResourceAsync(null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath("data.attributes").With(attributesObject => + { + attributesObject.Should().ContainPath(jsonPropertyName).With(attribute => attribute.Should().Be(defaultValue)); + }); + } + + [Theory] + [InlineData(nameof(AttributesInCreateResourceRequest.NonNullableReferenceType), "nonNullableReferenceType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNonNullableReferenceType), "requiredNonNullableReferenceType")] + public async Task Cannot_set_attribute_to_default_value(string attributePropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + NonNullableToOne = _fakers.ToOne.GenerateOne(), + RequiredNonNullableToOne = _fakers.ToOne.GenerateOne(), + NullableToOne = _fakers.NullableToOne.GenerateOne(), + RequiredNullableToOne = _fakers.NullableToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOffClient(wrapper.HttpClient); + + SetPropertyToDefaultValue(requestBody.Data.Attributes, attributePropertyName); + apiClient.MarkAsTracked(requestBody.Data.Attributes, attributePropertyName); + + // Act + Func action = async () => await apiClient.PostResourceAsync(null, requestBody); + + // Assert + ExceptionAssertions assertion = await action.Should().ThrowExactlyAsync(); + + assertion.Which.Message.Should().StartWith($"Cannot write a null value for property '{jsonPropertyName}'."); + assertion.Which.Message.Should().EndWith("Path 'data.attributes'."); + } + + [Theory] + [InlineData(nameof(AttributesInCreateResourceRequest.NonNullableReferenceType), "nonNullableReferenceType")] + [InlineData(nameof(AttributesInCreateResourceRequest.NullableReferenceType), "nullableReferenceType")] + [InlineData(nameof(AttributesInCreateResourceRequest.ValueType), "valueType")] + [InlineData(nameof(AttributesInCreateResourceRequest.NullableValueType), "nullableValueType")] + public async Task Can_omit_attribute(string attributePropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + NonNullableToOne = _fakers.ToOne.GenerateOne(), + RequiredNonNullableToOne = _fakers.ToOne.GenerateOne(), + NullableToOne = _fakers.NullableToOne.GenerateOne(), + RequiredNullableToOne = _fakers.NullableToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOffClient(wrapper.HttpClient); + + SetPropertyToInitialValue(requestBody.Data.Attributes, attributePropertyName); + apiClient.MarkAsTracked(requestBody.Data.Attributes); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PostResourceAsync(null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath("data.attributes").With(attributesObject => + { + attributesObject.Should().NotContainPath(jsonPropertyName); + }); + } + + [Theory] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNonNullableReferenceType), "requiredNonNullableReferenceType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNullableReferenceType), "requiredNullableReferenceType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredValueType), "requiredValueType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNullableValueType), "requiredNullableValueType")] + public async Task Cannot_omit_attribute(string attributePropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + NonNullableToOne = _fakers.ToOne.GenerateOne(), + RequiredNonNullableToOne = _fakers.ToOne.GenerateOne(), + NullableToOne = _fakers.NullableToOne.GenerateOne(), + RequiredNullableToOne = _fakers.NullableToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOffClient(wrapper.HttpClient); + + SetPropertyToInitialValue(requestBody.Data.Attributes, attributePropertyName); + apiClient.MarkAsTracked(requestBody.Data.Attributes); + + // Act + Func action = async () => await apiClient.PostResourceAsync(null, requestBody); + + // Assert + ExceptionAssertions assertion = await action.Should().ThrowExactlyAsync(); + + assertion.Which.Message.Should().Be( + $"Cannot write a default value for property '{jsonPropertyName}'. Property requires a non-default value. Path 'data.attributes'."); + } + + [Theory] + [InlineData(nameof(RelationshipsInCreateResourceRequest.NullableToOne), "nullableToOne")] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredNullableToOne), "requiredNullableToOne")] + public async Task Can_clear_relationship(string relationshipPropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + NonNullableToOne = _fakers.ToOne.GenerateOne(), + RequiredNonNullableToOne = _fakers.ToOne.GenerateOne(), + NullableToOne = _fakers.NullableToOne.GenerateOne(), + RequiredNullableToOne = _fakers.NullableToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOffClient(wrapper.HttpClient); + + SetDataPropertyToNull(requestBody.Data.Relationships, relationshipPropertyName); + apiClient.MarkAsTracked(requestBody.Data.Relationships, relationshipPropertyName); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PostResourceAsync(null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath($"data.relationships.{jsonPropertyName}.data").With(relationshipDataObject => + { + relationshipDataObject.ValueKind.Should().Be(JsonValueKind.Null); + }); + } + + [Theory] + [InlineData(nameof(RelationshipsInCreateResourceRequest.NonNullableToOne), "nonNullableToOne")] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredNonNullableToOne), "requiredNonNullableToOne")] + [InlineData(nameof(RelationshipsInCreateResourceRequest.ToMany), "toMany")] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredToMany), "requiredToMany")] + public async Task Cannot_clear_relationship(string relationshipPropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + NonNullableToOne = _fakers.ToOne.GenerateOne(), + RequiredNonNullableToOne = _fakers.ToOne.GenerateOne(), + NullableToOne = _fakers.NullableToOne.GenerateOne(), + RequiredNullableToOne = _fakers.NullableToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOffClient(wrapper.HttpClient); + + SetDataPropertyToNull(requestBody.Data.Relationships, relationshipPropertyName); + apiClient.MarkAsTracked(requestBody.Data.Relationships, relationshipPropertyName); + + // Act + Func action = async () => await apiClient.PostResourceAsync(null, requestBody); + + // Assert + ExceptionAssertions assertion = await action.Should().ThrowExactlyAsync(); + + assertion.Which.Message.Should().Be( + $"Cannot write a null value for property 'data'. Property requires a value. Path 'data.relationships.{jsonPropertyName}'."); + } + + [Theory] + [InlineData(nameof(RelationshipsInCreateResourceRequest.NonNullableToOne), "nonNullableToOne")] + [InlineData(nameof(RelationshipsInCreateResourceRequest.NullableToOne), "nullableToOne")] + [InlineData(nameof(RelationshipsInCreateResourceRequest.ToMany), "toMany")] + public async Task Can_omit_relationship(string relationshipPropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + NonNullableToOne = _fakers.ToOne.GenerateOne(), + RequiredNonNullableToOne = _fakers.ToOne.GenerateOne(), + NullableToOne = _fakers.NullableToOne.GenerateOne(), + RequiredNullableToOne = _fakers.NullableToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOffClient(wrapper.HttpClient); + + SetPropertyToInitialValue(requestBody.Data.Relationships, relationshipPropertyName); + apiClient.MarkAsTracked(requestBody.Data.Relationships); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PostResourceAsync(null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath("data.relationships").With(relationshipsObject => + { + relationshipsObject.Should().NotContainPath(jsonPropertyName); + }); + } + + [Theory] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredNonNullableToOne), "requiredNonNullableToOne")] + public async Task Cannot_omit_relationship(string relationshipPropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + NonNullableToOne = _fakers.ToOne.GenerateOne(), + RequiredNonNullableToOne = _fakers.ToOne.GenerateOne(), + NullableToOne = _fakers.NullableToOne.GenerateOne(), + RequiredNullableToOne = _fakers.NullableToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOffClient(wrapper.HttpClient); + + SetPropertyToInitialValue(requestBody.Data.Relationships, relationshipPropertyName); + apiClient.MarkAsTracked(requestBody.Data.Relationships); + + // Act + Func action = async () => await apiClient.PostResourceAsync(null, requestBody); + + // Assert + ExceptionAssertions assertion = await action.Should().ThrowExactlyAsync(); + + assertion.Which.Message.Should().Be( + $"Cannot write a null value for property 'id'. Property requires a value. Path 'data.relationships.{jsonPropertyName}.data'."); + } +} diff --git a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/NrtOnMsvOffFakers.cs b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/NrtOnMsvOffFakers.cs new file mode 100644 index 0000000000..e93076270c --- /dev/null +++ b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/NrtOnMsvOffFakers.cs @@ -0,0 +1,26 @@ +using Bogus; +using OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOff.GeneratedCode; + +namespace OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOff; + +internal sealed class NrtOnMsvOffFakers +{ + private readonly Lazy> _lazyPostAttributesFaker = + new(FakerFactory.Instance.Create); + + private readonly Lazy> _lazyPatchAttributesFaker = + new(FakerFactory.Instance.Create); + + private readonly Lazy> _lazyToOneFaker = new(FakerFactory.Instance.CreateForObjectWithResourceId); + + private readonly Lazy> _lazyNullableToOneFaker = + new(FakerFactory.Instance.CreateForObjectWithResourceId); + + private readonly Lazy> _lazyToManyFaker = new(FakerFactory.Instance.CreateForObjectWithResourceId); + + public Faker PostAttributes => _lazyPostAttributesFaker.Value; + public Faker PatchAttributes => _lazyPatchAttributesFaker.Value; + public Faker ToOne => _lazyToOneFaker.Value; + public Faker NullableToOne => _lazyNullableToOneFaker.Value; + public Faker ToMany => _lazyToManyFaker.Value; +} diff --git a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/NullabilityTests.cs b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/NullabilityTests.cs new file mode 100644 index 0000000000..8c7e3baa45 --- /dev/null +++ b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/NullabilityTests.cs @@ -0,0 +1,48 @@ +using System.Reflection; +using FluentAssertions; +using OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOff.GeneratedCode; +using Xunit; + +namespace OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOff; + +public sealed class NullabilityTests +{ + [Theory] + [InlineData(nameof(AttributesInCreateResourceRequest.NonNullableReferenceType), NullabilityState.NotNull)] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNonNullableReferenceType), NullabilityState.NotNull)] + [InlineData(nameof(AttributesInCreateResourceRequest.NullableReferenceType), NullabilityState.Nullable)] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNullableReferenceType), NullabilityState.Nullable)] + [InlineData(nameof(AttributesInCreateResourceRequest.ValueType), NullabilityState.NotNull)] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredValueType), NullabilityState.NotNull)] + [InlineData(nameof(AttributesInCreateResourceRequest.NullableValueType), NullabilityState.Nullable)] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNullableValueType), NullabilityState.Nullable)] + public void Nullability_of_generated_attribute_property_is_as_expected(string propertyName, NullabilityState expectedState) + { + // Act + PropertyInfo? property = typeof(AttributesInCreateResourceRequest).GetProperty(propertyName); + + // Assert + property.Should().NotBeNull(); + property.Should().HaveNullabilityState(expectedState); + } + + [Theory] + [InlineData(nameof(RelationshipsInCreateResourceRequest.NonNullableToOne), NullabilityState.NotNull)] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredNonNullableToOne), NullabilityState.NotNull)] + [InlineData(nameof(RelationshipsInCreateResourceRequest.NullableToOne), NullabilityState.Nullable)] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredNullableToOne), NullabilityState.Nullable)] + [InlineData(nameof(RelationshipsInCreateResourceRequest.ToMany), NullabilityState.NotNull)] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredToMany), NullabilityState.NotNull)] + public void Nullability_of_generated_relationship_property_is_as_expected(string propertyName, NullabilityState expectedState) + { + // Act + PropertyInfo? relationshipProperty = typeof(RelationshipsInCreateResourceRequest).GetProperty(propertyName); + + // Assert + relationshipProperty.Should().NotBeNull(); + + PropertyInfo? dataProperty = relationshipProperty.PropertyType.GetProperty("Data"); + dataProperty.Should().NotBeNull(); + dataProperty.Should().HaveNullabilityState(expectedState); + } +} diff --git a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/UpdateResourceTests.cs b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/UpdateResourceTests.cs new file mode 100644 index 0000000000..ace64a2bb2 --- /dev/null +++ b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/UpdateResourceTests.cs @@ -0,0 +1,143 @@ +using System.Net; +using System.Text.Json; +using FluentAssertions; +using FluentAssertions.Specialized; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using Newtonsoft.Json; +using OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOff.GeneratedCode; +using TestBuildingBlocks; +using Xunit; + +namespace OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOff; + +public sealed class UpdateResourceTests : BaseOpenApiNSwagClientTests +{ + private readonly NrtOnMsvOffFakers _fakers = new(); + + [Fact] + public async Task Cannot_omit_Id() + { + // Arrange + var requestBody = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Attributes = _fakers.PatchAttributes.GenerateOne(), + Relationships = new RelationshipsInUpdateResourceRequest + { + NonNullableToOne = _fakers.ToOne.GenerateOne(), + RequiredNonNullableToOne = _fakers.ToOne.GenerateOne(), + NullableToOne = _fakers.NullableToOne.GenerateOne(), + RequiredNullableToOne = _fakers.NullableToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOffClient(wrapper.HttpClient); + + // Act + Func action = async () => await apiClient.PatchResourceAsync(Unknown.StringId.Int32, null, requestBody); + + // Assert + ExceptionAssertions assertion = await action.Should().ThrowExactlyAsync(); + + assertion.Which.Message.Should().Be("Cannot write a null value for property 'id'. Property requires a value. Path 'data'."); + } + + [Theory] + [InlineData(nameof(AttributesInUpdateResourceRequest.NonNullableReferenceType), "nonNullableReferenceType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.RequiredNonNullableReferenceType), "requiredNonNullableReferenceType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.NullableReferenceType), "nullableReferenceType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.RequiredNullableReferenceType), "requiredNullableReferenceType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.ValueType), "valueType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.RequiredValueType), "requiredValueType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.NullableValueType), "nullableValueType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.RequiredNullableValueType), "requiredNullableValueType")] + public async Task Can_omit_attribute(string attributePropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Id = Unknown.StringId.Int32, + Attributes = _fakers.PatchAttributes.GenerateOne(), + Relationships = new RelationshipsInUpdateResourceRequest + { + NonNullableToOne = _fakers.ToOne.GenerateOne(), + RequiredNonNullableToOne = _fakers.ToOne.GenerateOne(), + NullableToOne = _fakers.NullableToOne.GenerateOne(), + RequiredNullableToOne = _fakers.NullableToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOffClient(wrapper.HttpClient); + + SetPropertyToInitialValue(requestBody.Data.Attributes, attributePropertyName); + apiClient.MarkAsTracked(requestBody.Data.Attributes); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(requestBody.Data.Id, null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath("data.attributes").With(attributesObject => + { + attributesObject.Should().NotContainPath(jsonPropertyName); + }); + } + + [Theory] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.NonNullableToOne), "nonNullableToOne")] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.RequiredNonNullableToOne), "requiredNonNullableToOne")] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.NullableToOne), "nullableToOne")] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.RequiredNullableToOne), "requiredNullableToOne")] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.ToMany), "toMany")] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.RequiredToMany), "requiredToMany")] + public async Task Can_omit_relationship(string relationshipPropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Id = Unknown.StringId.Int32, + Attributes = _fakers.PatchAttributes.GenerateOne(), + Relationships = new RelationshipsInUpdateResourceRequest + { + NonNullableToOne = _fakers.ToOne.GenerateOne(), + RequiredNonNullableToOne = _fakers.ToOne.GenerateOne(), + NullableToOne = _fakers.NullableToOne.GenerateOne(), + RequiredNullableToOne = _fakers.NullableToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOffClient(wrapper.HttpClient); + + SetPropertyToInitialValue(requestBody.Data.Relationships, relationshipPropertyName); + apiClient.MarkAsTracked(requestBody.Data.Relationships); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(requestBody.Data.Id, null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath("data.relationships").With(relationshipsObject => + { + relationshipsObject.Should().NotContainPath(jsonPropertyName); + }); + } +} diff --git a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/CreateResourceTests.cs b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/CreateResourceTests.cs new file mode 100644 index 0000000000..c54f675969 --- /dev/null +++ b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/CreateResourceTests.cs @@ -0,0 +1,347 @@ +using System.Net; +using System.Text.Json; +using FluentAssertions; +using FluentAssertions.Specialized; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using Newtonsoft.Json; +using OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOn.GeneratedCode; +using TestBuildingBlocks; +using Xunit; + +namespace OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOn; + +public sealed class CreateResourceTests : BaseOpenApiNSwagClientTests +{ + private readonly NrtOnMsvOnFakers _fakers = new(); + + [Theory] + [InlineData(nameof(AttributesInCreateResourceRequest.NullableReferenceType), "nullableReferenceType")] + [InlineData(nameof(AttributesInCreateResourceRequest.NullableValueType), "nullableValueType")] + [InlineData(nameof(AttributesInCreateResourceRequest.ValueType), "valueType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredValueType), "requiredValueType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNullableValueType), "requiredNullableValueType")] + public async Task Can_set_attribute_to_default_value(string attributePropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + NonNullableToOne = _fakers.ToOne.GenerateOne(), + RequiredNonNullableToOne = _fakers.ToOne.GenerateOne(), + NullableToOne = _fakers.NullableToOne.GenerateOne(), + RequiredNullableToOne = _fakers.ToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOnClient(wrapper.HttpClient); + + object? defaultValue = SetPropertyToDefaultValue(requestBody.Data.Attributes, attributePropertyName); + apiClient.MarkAsTracked(requestBody.Data.Attributes, attributePropertyName); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PostResourceAsync(null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath("data.attributes").With(attributesObject => + { + attributesObject.Should().ContainPath(jsonPropertyName).With(attribute => attribute.Should().Be(defaultValue)); + }); + } + + [Theory] + [InlineData(nameof(AttributesInCreateResourceRequest.NonNullableReferenceType), "nonNullableReferenceType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNonNullableReferenceType), "requiredNonNullableReferenceType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNullableReferenceType), "requiredNullableReferenceType")] + public async Task Cannot_set_attribute_to_default_value(string attributePropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + NonNullableToOne = _fakers.ToOne.GenerateOne(), + RequiredNonNullableToOne = _fakers.ToOne.GenerateOne(), + NullableToOne = _fakers.NullableToOne.GenerateOne(), + RequiredNullableToOne = _fakers.ToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOnClient(wrapper.HttpClient); + + SetPropertyToDefaultValue(requestBody.Data.Attributes, attributePropertyName); + apiClient.MarkAsTracked(requestBody.Data.Attributes, attributePropertyName); + + // Act + Func action = async () => await apiClient.PostResourceAsync(null, requestBody); + + // Assert + ExceptionAssertions assertion = await action.Should().ThrowExactlyAsync(); + + assertion.Which.Message.Should().Be($"Cannot write a null value for property '{jsonPropertyName}'. Property requires a value. Path 'data.attributes'."); + } + + [Theory] + [InlineData(nameof(AttributesInCreateResourceRequest.NullableReferenceType), "nullableReferenceType")] + [InlineData(nameof(AttributesInCreateResourceRequest.ValueType), "valueType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredValueType), "requiredValueType")] + [InlineData(nameof(AttributesInCreateResourceRequest.NullableValueType), "nullableValueType")] + public async Task Can_omit_attribute(string attributePropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + NonNullableToOne = _fakers.ToOne.GenerateOne(), + RequiredNonNullableToOne = _fakers.ToOne.GenerateOne(), + NullableToOne = _fakers.NullableToOne.GenerateOne(), + RequiredNullableToOne = _fakers.ToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOnClient(wrapper.HttpClient); + + SetPropertyToInitialValue(requestBody.Data.Attributes, attributePropertyName); + apiClient.MarkAsTracked(requestBody.Data.Attributes); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PostResourceAsync(null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath("data.attributes").With(attributesObject => + { + attributesObject.Should().NotContainPath(jsonPropertyName); + }); + } + + [Theory] + [InlineData(nameof(AttributesInCreateResourceRequest.NonNullableReferenceType), "nonNullableReferenceType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNonNullableReferenceType), "requiredNonNullableReferenceType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNullableReferenceType), "requiredNullableReferenceType")] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNullableValueType), "requiredNullableValueType")] + public async Task Cannot_omit_attribute(string attributePropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + NonNullableToOne = _fakers.ToOne.GenerateOne(), + RequiredNonNullableToOne = _fakers.ToOne.GenerateOne(), + NullableToOne = _fakers.NullableToOne.GenerateOne(), + RequiredNullableToOne = _fakers.ToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOnClient(wrapper.HttpClient); + + SetPropertyToInitialValue(requestBody.Data.Attributes, attributePropertyName); + apiClient.MarkAsTracked(requestBody.Data.Attributes); + + // Act + Func action = async () => await apiClient.PostResourceAsync(null, requestBody); + + // Assert + ExceptionAssertions assertion = await action.Should().ThrowExactlyAsync(); + + assertion.Which.Message.Should().Be( + $"Cannot write a default value for property '{jsonPropertyName}'. Property requires a non-default value. Path 'data.attributes'."); + } + + [Theory] + [InlineData(nameof(RelationshipsInCreateResourceRequest.NullableToOne), "nullableToOne")] + public async Task Can_clear_relationship(string relationshipPropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + NonNullableToOne = _fakers.ToOne.GenerateOne(), + RequiredNonNullableToOne = _fakers.ToOne.GenerateOne(), + NullableToOne = _fakers.NullableToOne.GenerateOne(), + RequiredNullableToOne = _fakers.ToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOnClient(wrapper.HttpClient); + + SetDataPropertyToNull(requestBody.Data.Relationships, relationshipPropertyName); + apiClient.MarkAsTracked(requestBody.Data.Relationships, relationshipPropertyName); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PostResourceAsync(null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath($"data.relationships.{jsonPropertyName}.data").With(relationshipDataObject => + { + relationshipDataObject.ValueKind.Should().Be(JsonValueKind.Null); + }); + } + + [Theory] + [InlineData(nameof(RelationshipsInCreateResourceRequest.NonNullableToOne), "nonNullableToOne")] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredNonNullableToOne), "requiredNonNullableToOne")] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredNullableToOne), "requiredNullableToOne")] + [InlineData(nameof(RelationshipsInCreateResourceRequest.ToMany), "toMany")] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredToMany), "requiredToMany")] + public async Task Cannot_clear_relationship(string relationshipPropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + NonNullableToOne = _fakers.ToOne.GenerateOne(), + RequiredNonNullableToOne = _fakers.ToOne.GenerateOne(), + NullableToOne = _fakers.NullableToOne.GenerateOne(), + RequiredNullableToOne = _fakers.ToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOnClient(wrapper.HttpClient); + + SetDataPropertyToNull(requestBody.Data.Relationships, relationshipPropertyName); + apiClient.MarkAsTracked(requestBody.Data.Relationships, relationshipPropertyName); + + // Act + Func action = async () => await apiClient.PostResourceAsync(null, requestBody); + + // Assert + ExceptionAssertions assertion = await action.Should().ThrowExactlyAsync(); + + assertion.Which.Message.Should().Be( + $"Cannot write a null value for property 'data'. Property requires a value. Path 'data.relationships.{jsonPropertyName}'."); + } + + [Theory] + [InlineData(nameof(RelationshipsInCreateResourceRequest.NullableToOne), "nullableToOne")] + [InlineData(nameof(RelationshipsInCreateResourceRequest.ToMany), "toMany")] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredToMany), "requiredToMany")] + public async Task Can_omit_relationship(string relationshipPropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + NonNullableToOne = _fakers.ToOne.GenerateOne(), + RequiredNonNullableToOne = _fakers.ToOne.GenerateOne(), + NullableToOne = _fakers.NullableToOne.GenerateOne(), + RequiredNullableToOne = _fakers.ToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOnClient(wrapper.HttpClient); + + SetPropertyToInitialValue(requestBody.Data.Relationships, relationshipPropertyName); + apiClient.MarkAsTracked(requestBody.Data.Relationships); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PostResourceAsync(null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath("data.relationships").With(relationshipsObject => + { + relationshipsObject.Should().NotContainPath(jsonPropertyName); + }); + } + + [Theory] + [InlineData(nameof(RelationshipsInCreateResourceRequest.NonNullableToOne), "nonNullableToOne")] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredNonNullableToOne), "requiredNonNullableToOne")] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredNullableToOne), "requiredNullableToOne")] + public async Task Cannot_omit_relationship(string relationshipPropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new CreateResourceRequestDocument + { + Data = new DataInCreateResourceRequest + { + Attributes = _fakers.PostAttributes.GenerateOne(), + Relationships = new RelationshipsInCreateResourceRequest + { + NonNullableToOne = _fakers.ToOne.GenerateOne(), + RequiredNonNullableToOne = _fakers.ToOne.GenerateOne(), + NullableToOne = _fakers.NullableToOne.GenerateOne(), + RequiredNullableToOne = _fakers.ToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOnClient(wrapper.HttpClient); + + SetPropertyToInitialValue(requestBody.Data.Relationships, relationshipPropertyName); + apiClient.MarkAsTracked(requestBody.Data.Relationships); + + // Act + Func action = async () => await apiClient.PostResourceAsync(null, requestBody); + + // Assert + ExceptionAssertions assertion = await action.Should().ThrowExactlyAsync(); + + assertion.Which.Message.Should().Be( + $"Cannot write a null value for property 'id'. Property requires a value. Path 'data.relationships.{jsonPropertyName}.data'."); + } +} diff --git a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/NrtOnMsvOnFakers.cs b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/NrtOnMsvOnFakers.cs new file mode 100644 index 0000000000..ccd784aff8 --- /dev/null +++ b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/NrtOnMsvOnFakers.cs @@ -0,0 +1,26 @@ +using Bogus; +using OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOn.GeneratedCode; + +namespace OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOn; + +internal sealed class NrtOnMsvOnFakers +{ + private readonly Lazy> _lazyPostAttributesFaker = + new(FakerFactory.Instance.Create); + + private readonly Lazy> _lazyPatchAttributesFaker = + new(FakerFactory.Instance.Create); + + private readonly Lazy> _lazyToOneFaker = new(FakerFactory.Instance.CreateForObjectWithResourceId); + + private readonly Lazy> _lazyNullableToOneFaker = + new(FakerFactory.Instance.CreateForObjectWithResourceId); + + private readonly Lazy> _lazyToManyFaker = new(FakerFactory.Instance.CreateForObjectWithResourceId); + + public Faker PostAttributes => _lazyPostAttributesFaker.Value; + public Faker PatchAttributes => _lazyPatchAttributesFaker.Value; + public Faker ToOne => _lazyToOneFaker.Value; + public Faker NullableToOne => _lazyNullableToOneFaker.Value; + public Faker ToMany => _lazyToManyFaker.Value; +} diff --git a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/NullabilityTests.cs b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/NullabilityTests.cs new file mode 100644 index 0000000000..15da38bfe1 --- /dev/null +++ b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/NullabilityTests.cs @@ -0,0 +1,48 @@ +using System.Reflection; +using FluentAssertions; +using OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOn.GeneratedCode; +using Xunit; + +namespace OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOn; + +public sealed class NullabilityTests +{ + [Theory] + [InlineData(nameof(AttributesInCreateResourceRequest.NonNullableReferenceType), NullabilityState.NotNull)] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNonNullableReferenceType), NullabilityState.NotNull)] + [InlineData(nameof(AttributesInCreateResourceRequest.NullableReferenceType), NullabilityState.Nullable)] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNullableReferenceType), NullabilityState.NotNull)] + [InlineData(nameof(AttributesInCreateResourceRequest.ValueType), NullabilityState.NotNull)] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredValueType), NullabilityState.NotNull)] + [InlineData(nameof(AttributesInCreateResourceRequest.NullableValueType), NullabilityState.Nullable)] + [InlineData(nameof(AttributesInCreateResourceRequest.RequiredNullableValueType), NullabilityState.NotNull)] + public void Nullability_of_generated_attribute_property_is_as_expected(string propertyName, NullabilityState expectedState) + { + // Act + PropertyInfo? property = typeof(AttributesInCreateResourceRequest).GetProperty(propertyName); + + // Assert + property.Should().NotBeNull(); + property.Should().HaveNullabilityState(expectedState); + } + + [Theory] + [InlineData(nameof(RelationshipsInCreateResourceRequest.NonNullableToOne), NullabilityState.NotNull)] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredNonNullableToOne), NullabilityState.NotNull)] + [InlineData(nameof(RelationshipsInCreateResourceRequest.NullableToOne), NullabilityState.Nullable)] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredNullableToOne), NullabilityState.NotNull)] + [InlineData(nameof(RelationshipsInCreateResourceRequest.ToMany), NullabilityState.NotNull)] + [InlineData(nameof(RelationshipsInCreateResourceRequest.RequiredToMany), NullabilityState.NotNull)] + public void Nullability_of_generated_relationship_property_is_as_expected(string propertyName, NullabilityState expectedState) + { + // Act + PropertyInfo? relationshipProperty = typeof(RelationshipsInCreateResourceRequest).GetProperty(propertyName); + + // Assert + relationshipProperty.Should().NotBeNull(); + + PropertyInfo? dataProperty = relationshipProperty.PropertyType.GetProperty("Data"); + dataProperty.Should().NotBeNull(); + dataProperty.Should().HaveNullabilityState(expectedState); + } +} diff --git a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/UpdateResourceTests.cs b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/UpdateResourceTests.cs new file mode 100644 index 0000000000..ce6774f834 --- /dev/null +++ b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/UpdateResourceTests.cs @@ -0,0 +1,143 @@ +using System.Net; +using System.Text.Json; +using FluentAssertions; +using FluentAssertions.Specialized; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using Newtonsoft.Json; +using OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOn.GeneratedCode; +using TestBuildingBlocks; +using Xunit; + +namespace OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOn; + +public sealed class UpdateResourceTests : BaseOpenApiNSwagClientTests +{ + private readonly NrtOnMsvOnFakers _fakers = new(); + + [Fact] + public async Task Cannot_omit_Id() + { + // Arrange + var requestBody = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Attributes = _fakers.PatchAttributes.GenerateOne(), + Relationships = new RelationshipsInUpdateResourceRequest + { + NonNullableToOne = _fakers.ToOne.GenerateOne(), + RequiredNonNullableToOne = _fakers.ToOne.GenerateOne(), + NullableToOne = _fakers.NullableToOne.GenerateOne(), + RequiredNullableToOne = _fakers.ToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOnClient(wrapper.HttpClient); + + // Act + Func action = async () => await apiClient.PatchResourceAsync(Unknown.StringId.Int32, null, requestBody); + + // Assert + ExceptionAssertions assertion = await action.Should().ThrowExactlyAsync(); + + assertion.Which.Message.Should().Be("Cannot write a null value for property 'id'. Property requires a value. Path 'data'."); + } + + [Theory] + [InlineData(nameof(AttributesInUpdateResourceRequest.NonNullableReferenceType), "nonNullableReferenceType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.RequiredNonNullableReferenceType), "requiredNonNullableReferenceType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.NullableReferenceType), "nullableReferenceType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.RequiredNullableReferenceType), "requiredNullableReferenceType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.ValueType), "valueType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.RequiredValueType), "requiredValueType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.NullableValueType), "nullableValueType")] + [InlineData(nameof(AttributesInUpdateResourceRequest.RequiredNullableValueType), "requiredNullableValueType")] + public async Task Can_omit_attribute(string attributePropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Id = Unknown.StringId.Int32, + Attributes = _fakers.PatchAttributes.GenerateOne(), + Relationships = new RelationshipsInUpdateResourceRequest + { + NonNullableToOne = _fakers.ToOne.GenerateOne(), + RequiredNonNullableToOne = _fakers.ToOne.GenerateOne(), + NullableToOne = _fakers.NullableToOne.GenerateOne(), + RequiredNullableToOne = _fakers.ToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOnClient(wrapper.HttpClient); + + SetPropertyToInitialValue(requestBody.Data.Attributes, attributePropertyName); + apiClient.MarkAsTracked(requestBody.Data.Attributes); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(requestBody.Data.Id, null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath("data.attributes").With(attributesObject => + { + attributesObject.Should().NotContainPath(jsonPropertyName); + }); + } + + [Theory] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.NonNullableToOne), "nonNullableToOne")] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.RequiredNonNullableToOne), "requiredNonNullableToOne")] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.NullableToOne), "nullableToOne")] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.RequiredNullableToOne), "requiredNullableToOne")] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.ToMany), "toMany")] + [InlineData(nameof(RelationshipsInUpdateResourceRequest.RequiredToMany), "requiredToMany")] + public async Task Can_omit_relationship(string relationshipPropertyName, string jsonPropertyName) + { + // Arrange + var requestBody = new UpdateResourceRequestDocument + { + Data = new DataInUpdateResourceRequest + { + Id = Unknown.StringId.Int32, + Attributes = _fakers.PatchAttributes.GenerateOne(), + Relationships = new RelationshipsInUpdateResourceRequest + { + NonNullableToOne = _fakers.ToOne.GenerateOne(), + RequiredNonNullableToOne = _fakers.ToOne.GenerateOne(), + NullableToOne = _fakers.NullableToOne.GenerateOne(), + RequiredNullableToOne = _fakers.ToOne.GenerateOne(), + ToMany = _fakers.ToMany.GenerateOne(), + RequiredToMany = _fakers.ToMany.GenerateOne() + } + } + }; + + using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null); + var apiClient = new NrtOnMsvOnClient(wrapper.HttpClient); + + SetPropertyToInitialValue(requestBody.Data.Relationships, relationshipPropertyName); + apiClient.MarkAsTracked(requestBody.Data.Relationships); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PatchResourceAsync(requestBody.Data.Id, null, requestBody)); + + // Assert + JsonElement document = wrapper.GetRequestBodyAsJson(); + + document.Should().ContainPath("data.relationships").With(relationshipsObject => + { + relationshipsObject.Should().NotContainPath(jsonPropertyName); + }); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/.editorconfig b/test/OpenApiNSwagEndToEndTests/.editorconfig new file mode 100644 index 0000000000..e2ec1cac44 --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/.editorconfig @@ -0,0 +1,3 @@ +# Workaround for incorrect nullability in NSwag generated clients. +[*Client.cs] +dotnet_diagnostic.CS8765.severity = none diff --git a/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicCreateResourceTests.cs b/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicCreateResourceTests.cs new file mode 100644 index 0000000000..e2cb3f9ed7 --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicCreateResourceTests.cs @@ -0,0 +1,205 @@ +using FluentAssertions; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using OpenApiNSwagEndToEndTests.AtomicOperations.GeneratedCode; +using OpenApiTests; +using OpenApiTests.AtomicOperations; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; +using CreateTeacherOperation = OpenApiNSwagEndToEndTests.AtomicOperations.GeneratedCode.CreateTeacherOperation; + +namespace OpenApiNSwagEndToEndTests.AtomicOperations; + +public sealed class AtomicCreateResourceTests : IClassFixture, OperationsDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, OperationsDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly OperationsFakers _fakers; + + public AtomicCreateResourceTests(IntegrationTestContext, OperationsDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseController(); + + _fakers = new OperationsFakers(testContext.Factory.Services); + } + + [Fact] + public async Task Can_create_resource_with_attributes() + { + // Arrange + Teacher newTeacher = _fakers.Teacher.GenerateOne(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new AtomicOperationsClient(httpClient); + + OperationsRequestDocument requestBody = new() + { + Atomic_operations = + [ + new CreateTeacherOperation + { + Data = new DataInCreateTeacherRequest + { + Attributes = new AttributesInCreateTeacherRequest + { + Name = newTeacher.Name, + EmailAddress = newTeacher.EmailAddress + } + } + } + ] + }; + + // Act + OperationsResponseDocument? response = await ApiResponse.TranslateAsync(async () => await apiClient.PostOperationsAsync(requestBody)); + + // Assert + response.Should().NotBeNull(); + + response.Atomic_results.Should().HaveCount(1); + DataInTeacherResponse teacherData = response.Atomic_results.ElementAt(0).Data.Should().BeOfType().Which; + + teacherData.Attributes.Should().NotBeNull(); + teacherData.Attributes.Name.Should().Be(newTeacher.Name); + teacherData.Attributes.EmailAddress.Should().Be(newTeacher.EmailAddress); + + long newTeacherId = long.Parse(teacherData.Id); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Teacher teacherInDatabase = await dbContext.Teachers.FirstWithIdAsync(newTeacherId); + + teacherInDatabase.Name.Should().Be(newTeacher.Name); + teacherInDatabase.EmailAddress.Should().Be(newTeacher.EmailAddress); + }); + } + + [Fact] + public async Task Can_create_resource_with_attributes_and_relationships() + { + // Arrange + Student existingStudent = _fakers.Student.GenerateOne(); + Course existingCourse = _fakers.Course.GenerateOne(); + Enrollment newEnrollment = _fakers.Enrollment.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.AddInRange(existingStudent, existingCourse); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new AtomicOperationsClient(httpClient); + + OperationsRequestDocument requestBody = new() + { + Atomic_operations = + [ + new CreateEnrollmentOperation + { + Data = new DataInCreateEnrollmentRequest + { + Attributes = new AttributesInCreateEnrollmentRequest + { + EnrolledAt = newEnrollment.EnrolledAt.ToDateTime(TimeOnly.MinValue) + }, + Relationships = new RelationshipsInCreateEnrollmentRequest + { + Course = new ToOneCourseInRequest + { + Data = new CourseIdentifierInRequest + { + Id = existingCourse.Id + } + }, + Student = new ToOneStudentInRequest + { + Data = new StudentIdentifierInRequest + { + Id = existingStudent.StringId! + } + } + } + } + } + ] + }; + + // Act + OperationsResponseDocument? response = await ApiResponse.TranslateAsync(async () => await apiClient.PostOperationsAsync(requestBody)); + + // Assert + response.Should().NotBeNull(); + + response.Atomic_results.Should().HaveCount(1); + DataInEnrollmentResponse enrollmentData = response.Atomic_results.ElementAt(0).Data.Should().BeOfType().Which; + + enrollmentData.Attributes.Should().NotBeNull(); + enrollmentData.Attributes.EnrolledAt.Should().Be(newEnrollment.EnrolledAt.ToDateTime(TimeOnly.MinValue)); + enrollmentData.Attributes.GraduatedAt.Should().BeNull(); + enrollmentData.Attributes.HasGraduated.Should().BeFalse(); + + long newEnrollmentId = long.Parse(enrollmentData.Id); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Enrollment enrollmentInDatabase = await dbContext.Enrollments.FirstWithIdAsync(newEnrollmentId); + + enrollmentInDatabase.EnrolledAt.Should().Be(newEnrollment.EnrolledAt); + enrollmentInDatabase.GraduatedAt.Should().BeNull(); + enrollmentInDatabase.HasGraduated.Should().BeFalse(); + }); + } + + [Fact] + public async Task Can_create_resource_with_client_generated_ID() + { + // Arrange + Course newCourse = _fakers.Course.GenerateOne(); + newCourse.Id = Guid.NewGuid(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new AtomicOperationsClient(httpClient); + + OperationsRequestDocument requestBody = new() + { + Atomic_operations = + [ + new CreateCourseOperation + { + Data = new DataInCreateCourseRequest + { + Id = newCourse.Id, + Attributes = new AttributesInCreateCourseRequest + { + Subject = newCourse.Subject + } + } + } + ] + }; + + // Act + OperationsResponseDocument? response = await ApiResponse.TranslateAsync(async () => await apiClient.PostOperationsAsync(requestBody)); + + // Assert + response.Should().BeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Course courseInDatabase = await dbContext.Courses.FirstWithIdAsync(newCourse.Id); + + courseInDatabase.Subject.Should().Be(newCourse.Subject); + courseInDatabase.Description.Should().BeNull(); + }); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicDeleteResourceTests.cs b/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicDeleteResourceTests.cs new file mode 100644 index 0000000000..d183c464aa --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicDeleteResourceTests.cs @@ -0,0 +1,78 @@ +using FluentAssertions; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using OpenApiNSwagEndToEndTests.AtomicOperations.GeneratedCode; +using OpenApiTests; +using OpenApiTests.AtomicOperations; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.AtomicOperations; + +public sealed class AtomicDeleteResourceTests : IClassFixture, OperationsDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, OperationsDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly OperationsFakers _fakers; + + public AtomicDeleteResourceTests(IntegrationTestContext, OperationsDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseController(); + + _fakers = new OperationsFakers(testContext.Factory.Services); + } + + [Fact] + public async Task Can_delete_resource() + { + // Arrange + Enrollment existingEnrollment = _fakers.Enrollment.GenerateOne(); + existingEnrollment.Student = _fakers.Student.GenerateOne(); + existingEnrollment.Course = _fakers.Course.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Enrollments.Add(existingEnrollment); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new AtomicOperationsClient(httpClient); + + OperationsRequestDocument requestBody = new() + { + Atomic_operations = + [ + new DeleteEnrollmentOperation + { + Ref = new EnrollmentIdentifierInRequest + { + Id = existingEnrollment.StringId! + } + } + ] + }; + + // Act + OperationsResponseDocument? response = await ApiResponse.TranslateAsync(async () => await apiClient.PostOperationsAsync(requestBody)); + + // Assert + response.Should().BeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Enrollment? enrollmentInDatabase = await dbContext.Enrollments.FirstWithIdOrDefaultAsync(existingEnrollment.Id); + + enrollmentInDatabase.Should().BeNull(); + }); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicLocalIdTests.cs b/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicLocalIdTests.cs new file mode 100644 index 0000000000..daf994d3bb --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicLocalIdTests.cs @@ -0,0 +1,217 @@ +using FluentAssertions; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using Microsoft.EntityFrameworkCore; +using OpenApiNSwagEndToEndTests.AtomicOperations.GeneratedCode; +using OpenApiTests; +using OpenApiTests.AtomicOperations; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.AtomicOperations; + +public sealed class AtomicLocalIdTests : IClassFixture, OperationsDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, OperationsDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly OperationsFakers _fakers; + + public AtomicLocalIdTests(IntegrationTestContext, OperationsDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseController(); + + _fakers = new OperationsFakers(testContext.Factory.Services); + } + + [Fact] + public async Task Can_use_local_IDs() + { + // Arrange + Teacher newTeacher = _fakers.Teacher.GenerateOne(); + Course newCourse = _fakers.Course.GenerateOne(); + newCourse.Id = Guid.NewGuid(); + Student newStudent = _fakers.Student.GenerateOne(); + DateOnly newEnrolledAt = _fakers.Enrollment.GenerateOne().EnrolledAt; + + const string teacherLocalId = "teacher-1"; + const string studentLocalId = "student-1"; + const string enrollmentLocalId = "enrollment-1"; + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new AtomicOperationsClient(httpClient); + + OperationsRequestDocument requestBody = new() + { + Atomic_operations = + [ + new CreateTeacherOperation + { + Data = new DataInCreateTeacherRequest + { + Lid = teacherLocalId, + Attributes = new AttributesInCreateTeacherRequest + { + Name = newTeacher.Name, + EmailAddress = newTeacher.EmailAddress + } + } + }, + new CreateCourseOperation + { + Data = new DataInCreateCourseRequest + { + Id = newCourse.Id, + Attributes = new AttributesInCreateCourseRequest + { + Subject = newCourse.Subject, + Description = newCourse.Description + } + } + }, + new AddToTeacherTeachesRelationshipOperation + { + Ref = new TeacherTeachesRelationshipIdentifier + { + Lid = teacherLocalId + }, + Data = + [ + new CourseIdentifierInRequest + { + Id = newCourse.Id + } + ] + }, + new CreateStudentOperation + { + Data = new DataInCreateStudentRequest + { + Lid = studentLocalId, + Attributes = new AttributesInCreateStudentRequest + { + Name = newStudent.Name, + EmailAddress = newStudent.EmailAddress + } + } + }, + new CreateEnrollmentOperation + { + Data = new DataInCreateEnrollmentRequest + { + Lid = enrollmentLocalId, + Attributes = new AttributesInCreateEnrollmentRequest + { + EnrolledAt = newEnrolledAt.ToDateTime(TimeOnly.MinValue) + }, + Relationships = new RelationshipsInCreateEnrollmentRequest + { + Course = new ToOneCourseInRequest + { + Data = new CourseIdentifierInRequest + { + Id = newCourse.Id + } + }, + Student = new ToOneStudentInRequest + { + Data = new StudentIdentifierInRequest + { + Lid = studentLocalId + } + } + } + } + }, + new UpdateStudentMentorRelationshipOperation + { + Ref = new StudentMentorRelationshipIdentifier + { + Lid = studentLocalId + }, + Data = new TeacherIdentifierInRequest + { + Lid = teacherLocalId + } + }, + new DeleteTeacherOperation + { + Ref = new TeacherIdentifierInRequest + { + Lid = teacherLocalId + } + } + ] + }; + + // Act + OperationsResponseDocument? response = await ApiResponse.TranslateAsync(async () => await apiClient.PostOperationsAsync(requestBody)); + + // Assert + response.Should().NotBeNull(); + + response.Atomic_results.Should().HaveCount(7); + + DataInTeacherResponse teacherData = response.Atomic_results.ElementAt(0).Data.Should().BeOfType().Which; + teacherData.Attributes.Should().NotBeNull(); + teacherData.Attributes.Name.Should().Be(newTeacher.Name); + teacherData.Attributes.EmailAddress.Should().Be(newTeacher.EmailAddress); + long newTeacherId = long.Parse(teacherData.Id); + + response.Atomic_results.ElementAt(1).Data.Should().BeNull(); + response.Atomic_results.ElementAt(2).Data.Should().BeNull(); + + DataInStudentResponse studentData = response.Atomic_results.ElementAt(3).Data.Should().BeOfType().Which; + studentData.Attributes.Should().NotBeNull(); + studentData.Attributes.Name.Should().Be(newStudent.Name); + studentData.Attributes.EmailAddress.Should().Be(newStudent.EmailAddress); + long newStudentId = long.Parse(studentData.Id); + + DataInEnrollmentResponse enrollmentData = response.Atomic_results.ElementAt(4).Data.Should().BeOfType().Which; + enrollmentData.Attributes.Should().NotBeNull(); + enrollmentData.Attributes.EnrolledAt.Should().Be(newEnrolledAt.ToDateTime(TimeOnly.MinValue)); + long newEnrollmentId = long.Parse(enrollmentData.Id); + + response.Atomic_results.ElementAt(5).Data.Should().BeNull(); + response.Atomic_results.ElementAt(6).Data.Should().BeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Teacher? teacherInDatabase = await dbContext.Teachers.FirstWithIdOrDefaultAsync(newTeacherId); + teacherInDatabase.Should().BeNull(); + + Course courseInDatabase = await dbContext.Courses.Include(course => course.TaughtBy).FirstWithIdAsync(newCourse.Id); + courseInDatabase.Subject.Should().Be(newCourse.Subject); + courseInDatabase.Description.Should().Be(newCourse.Description); + courseInDatabase.TaughtBy.Should().BeEmpty(); + + Student studentInDatabase = await dbContext.Students.Include(student => student.Mentor).FirstWithIdAsync(newStudentId); + studentInDatabase.Name.Should().Be(newStudent.Name); + studentInDatabase.EmailAddress.Should().Be(newStudent.EmailAddress); + studentInDatabase.Mentor.Should().BeNull(); + + // @formatter:wrap_chained_method_calls chop_always + // @formatter:keep_existing_linebreaks true + + Enrollment enrollmentInDatabase = await dbContext.Enrollments + .Include(enrollment => enrollment.Course) + .Include(enrollment => enrollment.Student) + .FirstWithIdAsync(newEnrollmentId); + + // @formatter:keep_existing_linebreaks restore + // @formatter:wrap_chained_method_calls restore + + enrollmentInDatabase.EnrolledAt.Should().Be(newEnrolledAt); + enrollmentInDatabase.Course.Should().NotBeNull(); + enrollmentInDatabase.Course.Id.Should().Be(newCourse.Id); + enrollmentInDatabase.Student.Id.Should().Be(newStudentId); + }); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicRelationshipTests.cs b/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicRelationshipTests.cs new file mode 100644 index 0000000000..39863bd8c7 --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicRelationshipTests.cs @@ -0,0 +1,261 @@ +using FluentAssertions; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using Microsoft.EntityFrameworkCore; +using OpenApiNSwagEndToEndTests.AtomicOperations.GeneratedCode; +using OpenApiTests; +using OpenApiTests.AtomicOperations; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.AtomicOperations; + +public sealed class AtomicRelationshipTests : IClassFixture, OperationsDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, OperationsDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly OperationsFakers _fakers; + + public AtomicRelationshipTests(IntegrationTestContext, OperationsDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseController(); + + _fakers = new OperationsFakers(testContext.Factory.Services); + } + + [Fact] + public async Task Can_update_ToOne_relationship() + { + // Arrange + Enrollment existingEnrollment = _fakers.Enrollment.GenerateOne(); + existingEnrollment.Student = _fakers.Student.GenerateOne(); + existingEnrollment.Course = _fakers.Course.GenerateOne(); + + Student existingStudent = _fakers.Student.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.AddInRange(existingEnrollment, existingStudent); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new AtomicOperationsClient(httpClient); + + OperationsRequestDocument requestBody = new() + { + Atomic_operations = + [ + new UpdateEnrollmentStudentRelationshipOperation + { + Ref = new EnrollmentStudentRelationshipIdentifier + { + Id = existingEnrollment.StringId! + }, + Data = new StudentIdentifierInRequest + { + Id = existingStudent.StringId! + } + } + ] + }; + + // Act + OperationsResponseDocument? response = await ApiResponse.TranslateAsync(async () => await apiClient.PostOperationsAsync(requestBody)); + + // Assert + response.Should().BeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Enrollment enrollmentInDatabase = await dbContext.Enrollments.Include(enrollment => enrollment.Student).FirstWithIdAsync(existingEnrollment.Id); + + enrollmentInDatabase.Student.Should().NotBeNull(); + enrollmentInDatabase.Student.Id.Should().Be(existingStudent.Id); + }); + } + + [Fact] + public async Task Can_update_ToMany_relationship() + { + // Arrange + Teacher existingTeacher = _fakers.Teacher.GenerateOne(); + existingTeacher.Teaches = _fakers.Course.GenerateSet(1); + List existingCourses = _fakers.Course.GenerateList(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Add(existingTeacher); + dbContext.AddRange(existingCourses); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new AtomicOperationsClient(httpClient); + + OperationsRequestDocument requestBody = new() + { + Atomic_operations = + [ + new UpdateTeacherTeachesRelationshipOperation + { + Ref = new TeacherTeachesRelationshipIdentifier + { + Id = existingTeacher.StringId! + }, + Data = + [ + new CourseIdentifierInRequest + { + Id = existingCourses.ElementAt(0).Id + }, + new CourseIdentifierInRequest + { + Id = existingCourses.ElementAt(1).Id + } + ] + } + ] + }; + + // Act + OperationsResponseDocument? response = await ApiResponse.TranslateAsync(async () => await apiClient.PostOperationsAsync(requestBody)); + + // Assert + response.Should().BeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Teacher teacherInDatabase = await dbContext.Teachers.Include(teacher => teacher.Teaches).FirstWithIdAsync(existingTeacher.Id); + + teacherInDatabase.Teaches.Should().HaveCount(2); + teacherInDatabase.Teaches.Should().ContainSingle(course => course.Id == existingCourses.ElementAt(0).Id); + teacherInDatabase.Teaches.Should().ContainSingle(course => course.Id == existingCourses.ElementAt(1).Id); + }); + } + + [Fact] + public async Task Can_add_to_ToMany_relationship() + { + // Arrange + Teacher existingTeacher = _fakers.Teacher.GenerateOne(); + existingTeacher.Teaches = _fakers.Course.GenerateSet(1); + List existingCourses = _fakers.Course.GenerateList(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Add(existingTeacher); + dbContext.AddRange(existingCourses); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new AtomicOperationsClient(httpClient); + + OperationsRequestDocument requestBody = new() + { + Atomic_operations = + [ + new AddToTeacherTeachesRelationshipOperation + { + Ref = new TeacherTeachesRelationshipIdentifier + { + Id = existingTeacher.StringId! + }, + Data = + [ + new CourseIdentifierInRequest + { + Id = existingCourses.ElementAt(0).Id + }, + new CourseIdentifierInRequest + { + Id = existingCourses.ElementAt(1).Id + } + ] + } + ] + }; + + // Act + OperationsResponseDocument? response = await ApiResponse.TranslateAsync(async () => await apiClient.PostOperationsAsync(requestBody)); + + // Assert + response.Should().BeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Teacher teacherInDatabase = await dbContext.Teachers.Include(teacher => teacher.Teaches).FirstWithIdAsync(existingTeacher.Id); + + teacherInDatabase.Teaches.Should().HaveCount(3); + teacherInDatabase.Teaches.Should().ContainSingle(course => course.Id == existingTeacher.Teaches.ElementAt(0).Id); + teacherInDatabase.Teaches.Should().ContainSingle(course => course.Id == existingCourses.ElementAt(0).Id); + teacherInDatabase.Teaches.Should().ContainSingle(course => course.Id == existingCourses.ElementAt(1).Id); + }); + } + + [Fact] + public async Task Can_remove_from_ToMany_relationship() + { + // Arrange + Teacher existingTeacher = _fakers.Teacher.GenerateOne(); + existingTeacher.Teaches = _fakers.Course.GenerateSet(3); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Add(existingTeacher); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new AtomicOperationsClient(httpClient); + + OperationsRequestDocument requestBody = new() + { + Atomic_operations = + [ + new RemoveFromTeacherTeachesRelationshipOperation + { + Ref = new TeacherTeachesRelationshipIdentifier + { + Id = existingTeacher.StringId! + }, + Data = + [ + new CourseIdentifierInRequest + { + Id = existingTeacher.Teaches.ElementAt(0).Id + }, + new CourseIdentifierInRequest + { + Id = existingTeacher.Teaches.ElementAt(2).Id + } + ] + } + ] + }; + + // Act + OperationsResponseDocument? response = await ApiResponse.TranslateAsync(async () => await apiClient.PostOperationsAsync(requestBody)); + + // Assert + response.Should().BeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Teacher teacherInDatabase = await dbContext.Teachers.Include(teacher => teacher.Teaches).FirstWithIdAsync(existingTeacher.Id); + + teacherInDatabase.Teaches.Should().HaveCount(1); + teacherInDatabase.Teaches.ElementAt(0).Id.Should().Be(existingTeacher.Teaches.ElementAt(1).Id); + }); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicUpdateResourceTests.cs b/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicUpdateResourceTests.cs new file mode 100644 index 0000000000..daf3704503 --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicUpdateResourceTests.cs @@ -0,0 +1,254 @@ +using FluentAssertions; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using JsonApiDotNetCore.Resources; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using OpenApiNSwagEndToEndTests.AtomicOperations.GeneratedCode; +using OpenApiTests; +using OpenApiTests.AtomicOperations; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.AtomicOperations; + +public sealed class AtomicUpdateResourceTests : IClassFixture, OperationsDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, OperationsDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly OperationsFakers _fakers; + + public AtomicUpdateResourceTests(IntegrationTestContext, OperationsDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseController(); + + testContext.ConfigureServices(services => services.AddScoped(typeof(IResourceChangeTracker<>), typeof(NeverSameResourceChangeTracker<>))); + + _fakers = new OperationsFakers(testContext.Factory.Services); + } + + [Fact] + public async Task Can_update_resource_with_attributes() + { + // Arrange + Student existingStudent = _fakers.Student.GenerateOne(); + string newName = _fakers.Student.GenerateOne().Name; + string? newEmailAddress = _fakers.Student.GenerateOne().EmailAddress; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Students.Add(existingStudent); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new AtomicOperationsClient(httpClient); + + OperationsRequestDocument requestBody = new() + { + Atomic_operations = + [ + new UpdateStudentOperation + { + Data = new DataInUpdateStudentRequest + { + Id = existingStudent.StringId!, + Attributes = new AttributesInUpdateStudentRequest + { + Name = newName, + EmailAddress = newEmailAddress + } + } + } + ] + }; + + // Act + OperationsResponseDocument? response = await ApiResponse.TranslateAsync(async () => await apiClient.PostOperationsAsync(requestBody)); + + // Assert + response.Should().NotBeNull(); + + response.Atomic_results.Should().HaveCount(1); + DataInStudentResponse studentData = response.Atomic_results.ElementAt(0).Data.Should().BeOfType().Which; + + studentData.Id.Should().Be(existingStudent.StringId); + studentData.Attributes.Should().NotBeNull(); + studentData.Attributes.Name.Should().Be(newName); + studentData.Attributes.EmailAddress.Should().Be(newEmailAddress); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Student studentInDatabase = await dbContext.Students.FirstWithIdAsync(existingStudent.Id); + + studentInDatabase.Name.Should().Be(newName); + studentInDatabase.EmailAddress.Should().Be(newEmailAddress); + }); + } + + [Fact] + public async Task Can_update_resource_with_attributes_using_ref() + { + // Arrange + Student existingStudent = _fakers.Student.GenerateOne(); + string? newEmailAddress = _fakers.Student.GenerateOne().EmailAddress; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Students.Add(existingStudent); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new AtomicOperationsClient(httpClient); + + OperationsRequestDocument requestBody = new() + { + Atomic_operations = + [ + new UpdateStudentOperation + { + Ref = new StudentIdentifierInRequest + { + Id = existingStudent.StringId! + }, + Data = new DataInUpdateStudentRequest + { + Id = existingStudent.StringId!, + Attributes = new AttributesInUpdateStudentRequest + { + EmailAddress = newEmailAddress + } + } + } + ] + }; + + // Act + OperationsResponseDocument? response = await ApiResponse.TranslateAsync(async () => await apiClient.PostOperationsAsync(requestBody)); + + // Assert + response.Should().NotBeNull(); + + response.Atomic_results.Should().HaveCount(1); + DataInStudentResponse studentData = response.Atomic_results.ElementAt(0).Data.Should().BeOfType().Which; + + studentData.Id.Should().Be(existingStudent.StringId); + studentData.Attributes.Should().NotBeNull(); + studentData.Attributes.Name.Should().Be(existingStudent.Name); + studentData.Attributes.EmailAddress.Should().Be(newEmailAddress); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Student studentInDatabase = await dbContext.Students.FirstWithIdAsync(existingStudent.Id); + + studentInDatabase.Name.Should().Be(existingStudent.Name); + studentInDatabase.EmailAddress.Should().Be(newEmailAddress); + }); + } + + [Fact] + public async Task Can_update_resource_with_attributes_and_relationships() + { + // Arrange + Enrollment existingEnrollment = _fakers.Enrollment.GenerateOne(); + existingEnrollment.Student = _fakers.Student.GenerateOne(); + existingEnrollment.Course = _fakers.Course.GenerateOne(); + + Student existingStudent = _fakers.Student.GenerateOne(); + Course existingCourse = _fakers.Course.GenerateOne(); + DateOnly newEnrolledAt = _fakers.Enrollment.GenerateOne().EnrolledAt; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.AddInRange(existingEnrollment, existingStudent, existingCourse); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new AtomicOperationsClient(httpClient); + + OperationsRequestDocument requestBody = new() + { + Atomic_operations = + [ + new UpdateEnrollmentOperation + { + Data = new DataInUpdateEnrollmentRequest + { + Id = existingEnrollment.StringId!, + Attributes = new AttributesInUpdateEnrollmentRequest + { + EnrolledAt = newEnrolledAt.ToDateTime(TimeOnly.MinValue) + }, + Relationships = new RelationshipsInUpdateEnrollmentRequest + { + Course = new ToOneCourseInRequest + { + Data = new CourseIdentifierInRequest + { + Id = existingCourse.Id + } + }, + Student = new ToOneStudentInRequest + { + Data = new StudentIdentifierInRequest + { + Id = existingStudent.StringId! + } + } + } + } + } + ] + }; + + // Act + OperationsResponseDocument? response = await ApiResponse.TranslateAsync(async () => await apiClient.PostOperationsAsync(requestBody)); + + // Assert + response.Should().NotBeNull(); + + response.Atomic_results.Should().HaveCount(1); + DataInEnrollmentResponse enrollmentData = response.Atomic_results.ElementAt(0).Data.Should().BeOfType().Which; + + enrollmentData.Id.Should().Be(existingEnrollment.StringId); + enrollmentData.Attributes.Should().NotBeNull(); + enrollmentData.Attributes.EnrolledAt.Should().Be(newEnrolledAt.ToDateTime(TimeOnly.MinValue)); + enrollmentData.Attributes.GraduatedAt.Should().Be(existingEnrollment.GraduatedAt!.Value.ToDateTime(TimeOnly.MinValue)); + enrollmentData.Attributes.HasGraduated.Should().Be(existingEnrollment.HasGraduated); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + // @formatter:wrap_chained_method_calls chop_always + // @formatter:keep_existing_linebreaks true + + Enrollment enrollmentInDatabase = await dbContext.Enrollments + .Include(enrollment => enrollment.Student) + .Include(enrollment => enrollment.Course) + .FirstWithIdAsync(existingEnrollment.Id); + + // @formatter:keep_existing_linebreaks restore + // @formatter:wrap_chained_method_calls restore + + enrollmentInDatabase.EnrolledAt.Should().Be(newEnrolledAt); + enrollmentInDatabase.GraduatedAt.Should().Be(existingEnrollment.GraduatedAt); + enrollmentInDatabase.HasGraduated.Should().Be(existingEnrollment.HasGraduated); + + enrollmentInDatabase.Student.Should().NotBeNull(); + enrollmentInDatabase.Student.Id.Should().Be(existingStudent.Id); + + enrollmentInDatabase.Course.Should().NotBeNull(); + enrollmentInDatabase.Course.Id.Should().Be(existingCourse.Id); + }); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/ClientIdGenerationModes/ClientIdGenerationModesTests.cs b/test/OpenApiNSwagEndToEndTests/ClientIdGenerationModes/ClientIdGenerationModesTests.cs new file mode 100644 index 0000000000..dc0d14d45c --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/ClientIdGenerationModes/ClientIdGenerationModesTests.cs @@ -0,0 +1,263 @@ +using System.Net; +using FluentAssertions; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using OpenApiNSwagEndToEndTests.ClientIdGenerationModes.GeneratedCode; +using OpenApiTests; +using OpenApiTests.ClientIdGenerationModes; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.ClientIdGenerationModes; + +public sealed class ClientIdGenerationModesTests + : IClassFixture, ClientIdGenerationDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, ClientIdGenerationDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly ClientIdGenerationFakers _fakers = new(); + + public ClientIdGenerationModesTests(IntegrationTestContext, ClientIdGenerationDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + } + + [Fact] + public async Task Cannot_create_resource_without_ID_when_supplying_ID_is_required() + { + // Arrange + Player newPlayer = _fakers.Player.GenerateOne(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + ClientIdGenerationModesClient apiClient = new(httpClient); + + var requestBody = new CreatePlayerRequestDocument + { + Data = new DataInCreatePlayerRequest + { + Attributes = new AttributesInCreatePlayerRequest + { + UserName = newPlayer.UserName + } + } + }; + + // Act + Func action = async () => await ApiResponse.TranslateAsync(async () => await apiClient.PostPlayerAsync(requestBody)); + + // Assert + ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; + exception.StatusCode.Should().Be((int)HttpStatusCode.UnprocessableEntity); + exception.Message.Should().Be("HTTP 422: Validation of the request body failed."); + exception.Result.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Result.Errors.ElementAt(0); + error.Status.Should().Be("422"); + error.Title.Should().Be("Failed to deserialize request body: The 'id' element is invalid."); + error.Detail.Should().BeNull(); + error.Source.Should().NotBeNull(); + error.Source.Pointer.Should().Be("/data"); + } + + [Fact] + public async Task Can_create_resource_with_ID_when_supplying_ID_is_required() + { + // Arrange + Player newPlayer = _fakers.Player.GenerateOne(); + newPlayer.Id = Guid.NewGuid(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + ClientIdGenerationModesClient apiClient = new(httpClient); + + var requestBody = new CreatePlayerRequestDocument + { + Data = new DataInCreatePlayerRequest + { + Id = newPlayer.Id, + Attributes = new AttributesInCreatePlayerRequest + { + UserName = newPlayer.UserName + } + } + }; + + // Act + PrimaryPlayerResponseDocument? response = await ApiResponse.TranslateAsync(async () => await apiClient.PostPlayerAsync(requestBody)); + + // Assert + response.Should().BeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Player playerInDatabase = await dbContext.Players.FirstWithIdAsync(newPlayer.Id); + + playerInDatabase.UserName.Should().Be(newPlayer.UserName); + }); + } + + [Fact] + public async Task Can_create_resource_without_ID_when_supplying_ID_is_allowed() + { + // Arrange + Game newGame = _fakers.Game.GenerateOne(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + ClientIdGenerationModesClient apiClient = new(httpClient); + + var requestBody = new CreateGameRequestDocument + { + Data = new DataInCreateGameRequest + { + Attributes = new AttributesInCreateGameRequest + { + Title = newGame.Title, + PurchasePrice = (double)newGame.PurchasePrice + } + } + }; + + // Act + PrimaryGameResponseDocument? response = await ApiResponse.TranslateAsync(async () => await apiClient.PostGameAsync(requestBody)); + + // Assert + response.Should().NotBeNull(); + response.Data.Id.Should().NotBe(Guid.Empty); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Game gameInDatabase = await dbContext.Games.FirstWithIdAsync(response.Data.Id); + + gameInDatabase.Title.Should().Be(newGame.Title); + gameInDatabase.PurchasePrice.Should().Be(newGame.PurchasePrice); + }); + } + + [Fact] + public async Task Can_create_resource_with_ID_when_supplying_ID_is_allowed() + { + // Arrange + Game newGame = _fakers.Game.GenerateOne(); + newGame.Id = Guid.NewGuid(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + ClientIdGenerationModesClient apiClient = new(httpClient); + + var requestBody = new CreateGameRequestDocument + { + Data = new DataInCreateGameRequest + { + Id = newGame.Id, + Attributes = new AttributesInCreateGameRequest + { + Title = newGame.Title, + PurchasePrice = (double)newGame.PurchasePrice + } + } + }; + + // Act + PrimaryGameResponseDocument? response = await ApiResponse.TranslateAsync(async () => await apiClient.PostGameAsync(requestBody)); + + // Assert + response.Should().BeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Game gameInDatabase = await dbContext.Games.FirstWithIdAsync(newGame.Id); + + gameInDatabase.Title.Should().Be(newGame.Title); + gameInDatabase.PurchasePrice.Should().Be(newGame.PurchasePrice); + }); + } + + [Fact] + public async Task Cannot_create_resource_with_existing_ID_when_supplying_ID_is_allowed() + { + // Arrange + Game existingGame = _fakers.Game.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Games.Add(existingGame); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + ClientIdGenerationModesClient apiClient = new(httpClient); + + var requestBody = new CreateGameRequestDocument + { + Data = new DataInCreateGameRequest + { + Id = existingGame.Id, + Attributes = new AttributesInCreateGameRequest + { + Title = existingGame.Title, + PurchasePrice = (double)existingGame.PurchasePrice + } + } + }; + + // Act + Func action = async () => _ = await apiClient.PostGameAsync(requestBody); + + // Assert + ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; + exception.StatusCode.Should().Be((int)HttpStatusCode.Conflict); + exception.Message.Should().Be("HTTP 409: The request body contains conflicting information or another resource with the same ID already exists."); + exception.Result.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Result.Errors.ElementAt(0); + error.Status.Should().Be("409"); + error.Title.Should().Be("Another resource with the specified ID already exists."); + error.Detail.Should().Be($"Another resource of type 'games' with ID '{existingGame.StringId}' already exists."); + } + + [Fact] + public async Task Can_create_resource_without_ID_when_supplying_ID_is_forbidden() + { + // Arrange + PlayerGroup newPlayerGroup = _fakers.Group.GenerateOne(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + ClientIdGenerationModesClient apiClient = new(httpClient); + + var requestBody = new CreatePlayerGroupRequestDocument + { + Data = new DataInCreatePlayerGroupRequest + { + Attributes = new AttributesInCreatePlayerGroupRequest + { + Name = newPlayerGroup.Name + } + } + }; + + // Act + PrimaryPlayerGroupResponseDocument? response = await ApiResponse.TranslateAsync(async () => await apiClient.PostPlayerGroupAsync(requestBody)); + + // Assert + response.Should().NotBeNull(); + response.Data.Id.Should().NotBeNullOrEmpty(); + + long newPlayerGroupId = long.Parse(response.Data.Id); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + PlayerGroup playerGroupInDatabase = await dbContext.PlayerGroups.FirstWithIdAsync(newPlayerGroupId); + + playerGroupInDatabase.Name.Should().Be(newPlayerGroup.Name); + }); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/Headers/ETagTests.cs b/test/OpenApiNSwagEndToEndTests/Headers/ETagTests.cs new file mode 100644 index 0000000000..88e9f84a01 --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/Headers/ETagTests.cs @@ -0,0 +1,208 @@ +using System.Net; +using FluentAssertions; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using Microsoft.Net.Http.Headers; +using OpenApiNSwagEndToEndTests.Headers.GeneratedCode; +using OpenApiTests; +using OpenApiTests.Headers; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.Headers; + +public sealed class ETagTests : IClassFixture, HeaderDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, HeaderDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly HeaderFakers _fakers = new(); + + public ETagTests(IntegrationTestContext, HeaderDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseController(); + } + + [Fact] + public async Task Returns_ETag_for_HEAD_request() + { + // Arrange + List countries = _fakers.Country.GenerateList(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Countries.AddRange(countries); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new HeadersClient(httpClient); + + // Act + ApiResponse response = await apiClient.HeadCountryCollectionAsync(); + + // Assert + response.StatusCode.Should().Be((int)HttpStatusCode.OK); + + string[] eTagHeaderValues = response.Headers.Should().ContainKey(HeaderNames.ETag).WhoseValue.ToArray(); + eTagHeaderValues.Should().HaveCount(1); + eTagHeaderValues[0].Should().Match("\"*\""); + } + + [Fact] + public async Task Returns_ETag_for_GET_request() + { + // Arrange + List countries = _fakers.Country.GenerateList(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Countries.AddRange(countries); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new HeadersClient(httpClient); + + // Act + ApiResponse response = await apiClient.GetCountryCollectionAsync(); + + // Assert + response.StatusCode.Should().Be((int)HttpStatusCode.OK); + + string[] eTagHeaderValues = response.Headers.Should().ContainKey(HeaderNames.ETag).WhoseValue.ToArray(); + eTagHeaderValues.Should().HaveCount(1); + eTagHeaderValues[0].Should().Match("\"*\""); + + response.Result.Should().NotBeNull(); + } + + [Fact] + public async Task Returns_no_ETag_for_failed_GET_request() + { + // Arrange + Guid unknownCountryId = Unknown.TypedId.Guid; + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new HeadersClient(httpClient); + + // Act + Func action = async () => await apiClient.GetCountryAsync(unknownCountryId); + + // Assert + ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; + exception.StatusCode.Should().Be((int)HttpStatusCode.NotFound); + exception.Message.Should().Be("HTTP 404: The country does not exist."); + exception.Headers.Should().NotContainKey(HeaderNames.ETag); + exception.Result.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Result.Errors.ElementAt(0); + error.Status.Should().Be("404"); + error.Title.Should().Be("The requested resource does not exist."); + error.Detail.Should().Be($"Resource of type 'countries' with ID '{unknownCountryId}' does not exist."); + } + + [Fact] + public async Task Returns_no_ETag_for_POST_request() + { + // Arrange + Country newCountry = _fakers.Country.GenerateOne(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new HeadersClient(httpClient); + + var requestBody = new CreateCountryRequestDocument + { + Data = new DataInCreateCountryRequest + { + Attributes = new AttributesInCreateCountryRequest + { + Name = newCountry.Name, + Population = newCountry.Population + } + } + }; + + // Act + ApiResponse response = await ApiResponse.TranslateAsync(async () => await apiClient.PostCountryAsync(requestBody)); + + // Assert + response.StatusCode.Should().Be((int)HttpStatusCode.Created); + + response.Headers.Should().NotContainKey(HeaderNames.ETag); + + response.Result.Should().NotBeNull(); + } + + [Fact] + public async Task Returns_NotModified_for_matching_ETag() + { + // Arrange + List countries = _fakers.Country.GenerateList(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Countries.AddRange(countries); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new HeadersClient(httpClient); + + ApiResponse response1 = await apiClient.GetCountryCollectionAsync(); + + string responseETag = response1.Headers[HeaderNames.ETag].Single(); + + // Act + ApiResponse response2 = + await ApiResponse.TranslateAsync(async () => await apiClient.GetCountryCollectionAsync(null, responseETag)); + + // Assert + response2.StatusCode.Should().Be((int)HttpStatusCode.NotModified); + + string[] eTagHeaderValues = response2.Headers.Should().ContainKey(HeaderNames.ETag).WhoseValue.ToArray(); + eTagHeaderValues.Should().HaveCount(1); + eTagHeaderValues[0].Should().Be(responseETag); + + response2.Result.Should().BeNull(); + } + + [Fact] + public async Task Returns_content_for_mismatching_ETag() + { + // Arrange + List countries = _fakers.Country.GenerateList(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Countries.AddRange(countries); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new HeadersClient(httpClient); + + // Act + ApiResponse response = await apiClient.GetCountryCollectionAsync(null, "\"Not-a-matching-value\""); + + // Assert + response.StatusCode.Should().Be((int)HttpStatusCode.OK); + + string[] eTagHeaderValues = response.Headers.Should().ContainKey(HeaderNames.ETag).WhoseValue.ToArray(); + eTagHeaderValues.Should().HaveCount(1); + eTagHeaderValues[0].Should().Match("\"*\""); + + response.Result.Should().NotBeNull(); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/Headers/HeaderTests.cs b/test/OpenApiNSwagEndToEndTests/Headers/HeaderTests.cs new file mode 100644 index 0000000000..b93912ea56 --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/Headers/HeaderTests.cs @@ -0,0 +1,173 @@ +using System.Net; +using FluentAssertions; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using Microsoft.Net.Http.Headers; +using OpenApiNSwagEndToEndTests.Headers.GeneratedCode; +using OpenApiTests; +using OpenApiTests.Headers; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.Headers; + +public sealed class HeaderTests : IClassFixture, HeaderDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, HeaderDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly HeaderFakers _fakers = new(); + + public HeaderTests(IntegrationTestContext, HeaderDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseController(); + } + + [Fact] + public async Task Returns_Location_for_post_resource_request() + { + // Arrange + Country newCountry = _fakers.Country.GenerateOne(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new HeadersClient(httpClient); + + var requestBody = new CreateCountryRequestDocument + { + Data = new DataInCreateCountryRequest + { + Attributes = new AttributesInCreateCountryRequest + { + Name = newCountry.Name, + Population = newCountry.Population + } + } + }; + + // Act + ApiResponse response = await ApiResponse.TranslateAsync(async () => await apiClient.PostCountryAsync(requestBody)); + + // Assert + response.StatusCode.Should().Be((int)HttpStatusCode.Created); + + response.Result.Should().NotBeNull(); + + string[] locationHeaderValues = response.Headers.Should().ContainKey(HeaderNames.Location).WhoseValue.ToArray(); + locationHeaderValues.Should().HaveCount(1); + locationHeaderValues[0].Should().Be($"/countries/{response.Result.Data.Id}"); + } + + [Fact] + public async Task Returns_ContentLength_for_head_primary_resources_request() + { + // Arrange + Country existingCountry = _fakers.Country.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Countries.Add(existingCountry); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new HeadersClient(httpClient); + + // Act + ApiResponse response = await apiClient.HeadCountryCollectionAsync(); + + // Assert + response.StatusCode.Should().Be((int)HttpStatusCode.OK); + + string[] contentLengthHeaderValues = response.Headers.Should().ContainKey(HeaderNames.ContentLength).WhoseValue.ToArray(); + contentLengthHeaderValues.Should().HaveCount(1); + long.Parse(contentLengthHeaderValues[0]).Should().BeGreaterThan(0); + } + + [Fact] + public async Task Returns_ContentLength_for_head_primary_resource_request() + { + // Arrange + Country existingCountry = _fakers.Country.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Countries.Add(existingCountry); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new HeadersClient(httpClient); + + // Act + ApiResponse response = await apiClient.HeadCountryAsync(existingCountry.Id); + + // Assert + response.StatusCode.Should().Be((int)HttpStatusCode.OK); + + string[] contentLengthHeaderValues = response.Headers.Should().ContainKey(HeaderNames.ContentLength).WhoseValue.ToArray(); + contentLengthHeaderValues.Should().HaveCount(1); + long.Parse(contentLengthHeaderValues[0]).Should().BeGreaterThan(0); + } + + [Fact] + public async Task Returns_ContentLength_for_head_secondary_resource_request() + { + // Arrange + Country existingCountry = _fakers.Country.GenerateOne(); + existingCountry.Languages = _fakers.Language.GenerateSet(1); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Countries.Add(existingCountry); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new HeadersClient(httpClient); + + // Act + ApiResponse response = await apiClient.HeadCountryLanguagesAsync(existingCountry.Id); + + // Assert + response.StatusCode.Should().Be((int)HttpStatusCode.OK); + + string[] contentLengthHeaderValues = response.Headers.Should().ContainKey(HeaderNames.ContentLength).WhoseValue.ToArray(); + contentLengthHeaderValues.Should().HaveCount(1); + long.Parse(contentLengthHeaderValues[0]).Should().BeGreaterThan(0); + } + + [Fact] + public async Task Returns_ContentLength_for_head_relationship_request() + { + // Arrange + Country existingCountry = _fakers.Country.GenerateOne(); + existingCountry.Languages = _fakers.Language.GenerateSet(1); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Countries.Add(existingCountry); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new HeadersClient(httpClient); + + // Act + ApiResponse response = await apiClient.HeadCountryLanguagesRelationshipAsync(existingCountry.Id); + + // Assert + response.StatusCode.Should().Be((int)HttpStatusCode.OK); + + string[] contentLengthHeaderValues = response.Headers.Should().ContainKey(HeaderNames.ContentLength).WhoseValue.ToArray(); + contentLengthHeaderValues.Should().HaveCount(1); + long.Parse(contentLengthHeaderValues[0]).Should().BeGreaterThan(0); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/Links/AlternateOpenApiRouteTests.cs b/test/OpenApiNSwagEndToEndTests/Links/AlternateOpenApiRouteTests.cs new file mode 100644 index 0000000000..1166a8bc0d --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/Links/AlternateOpenApiRouteTests.cs @@ -0,0 +1,56 @@ +using FluentAssertions; +using Microsoft.Extensions.DependencyInjection; +using OpenApiNSwagEndToEndTests.Links.GeneratedCode; +using OpenApiTests; +using OpenApiTests.Links; +using Swashbuckle.AspNetCore.Swagger; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.Links; + +public sealed class AlternateOpenApiRouteTests : IClassFixture, LinkDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, LinkDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly LinkFakers _fakers = new(); + + public AlternateOpenApiRouteTests(IntegrationTestContext, LinkDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.ConfigureServices(services => + services.Configure(options => options.RouteTemplate = "/api-docs/{documentName}/swagger.yaml")); + + testContext.UseController(); + } + + [Fact] + public async Task DescribedBy_link_matches_alternate_OpenAPI_route() + { + // Arrange + Excursion excursion = _fakers.Excursion.GenerateOne(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new LinksClient(httpClient); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Excursions.Add(excursion); + await dbContext.SaveChangesAsync(); + }); + + // Act + PrimaryExcursionResponseDocument response = await apiClient.GetExcursionAsync(excursion.StringId!); + + // Assert + response.Links.Describedby.Should().Be("/api-docs/v1/swagger.yaml"); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/ModelStateValidation/ModelStateValidationTests.cs b/test/OpenApiNSwagEndToEndTests/ModelStateValidation/ModelStateValidationTests.cs new file mode 100644 index 0000000000..bc15e6ee62 --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/ModelStateValidation/ModelStateValidationTests.cs @@ -0,0 +1,551 @@ +using FluentAssertions; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using Microsoft.Extensions.DependencyInjection; +using OpenApiNSwagEndToEndTests.ModelStateValidation.GeneratedCode; +using OpenApiTests; +using OpenApiTests.ModelStateValidation; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.ModelStateValidation; + +public sealed class ModelStateValidationTests + : IClassFixture, ModelStateValidationDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, ModelStateValidationDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly ModelStateValidationFakers _fakers = new(); + + public ModelStateValidationTests(IntegrationTestContext, ModelStateValidationDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseController(); + + var options = testContext.Factory.Services.GetRequiredService(); + options.SerializerOptions.Converters.Add(new UtcDateTimeJsonConverter()); + } + + [Theory] + [InlineData("a")] + [InlineData("abcdefghijklmnopqrstu")] + public async Task Cannot_exceed_length_constraint(string firstName) + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + ModelStateValidationClient apiClient = new(httpClient); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + FirstName = firstName, + LastName = newAccount.LastName + } + } + }; + + // Act + Func action = () => apiClient.PostSocialMediaAccountAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync>()).Which.Result; + response.Errors.Should().HaveCount(1); + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be("The field FirstName must be a string or collection type with a minimum length of '2' and maximum length of '20'."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/firstName"); + } + + [Theory] + [InlineData("ab")] + [InlineData("abcdefghijklmnopqrs")] + public async Task Cannot_exceed_string_length_constraint(string userName) + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + ModelStateValidationClient apiClient = new(httpClient); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + UserName = userName + } + } + }; + + // Act + Func action = () => apiClient.PostSocialMediaAccountAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync>()).Which.Result; + response.Errors.Should().HaveCount(1); + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be("The field UserName must be a string with a minimum length of 3 and a maximum length of 18."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/userName"); + } + + [Fact] + public async Task Cannot_violate_regular_expression_constraint() + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + ModelStateValidationClient apiClient = new(httpClient); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + UserName = "aB1" + } + } + }; + + // Act + Func action = () => apiClient.PostSocialMediaAccountAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync>()).Which.Result; + response.Errors.Should().HaveCount(1); + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be("Only letters are allowed."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/userName"); + } + + [Fact] + public async Task Cannot_use_invalid_credit_card_number() + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + ModelStateValidationClient apiClient = new(httpClient); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + CreditCard = "123-456" + } + } + }; + + // Act + Func action = () => apiClient.PostSocialMediaAccountAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync>()).Which.Result; + response.Errors.Should().HaveCount(1); + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be("The CreditCard field is not a valid credit card number."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/creditCard"); + } + + [Fact] + public async Task Cannot_use_invalid_email_address() + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + ModelStateValidationClient apiClient = new(httpClient); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + Email = "abc" + } + } + }; + + // Act + Func action = () => apiClient.PostSocialMediaAccountAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync>()).Which.Result; + response.Errors.Should().HaveCount(1); + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be("The Email field is not a valid e-mail address."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/email"); + } + + [Fact] + public async Task Cannot_exceed_min_length_constraint() + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + ModelStateValidationClient apiClient = new(httpClient); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + // Using -3 instead of -1 to compensate for base64 padding. + Password = Enumerable.Repeat((byte)'X', SocialMediaAccount.MinPasswordChars - 3).ToArray() + } + } + }; + + // Act + Func action = () => apiClient.PostSocialMediaAccountAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync>()).Which.Result; + response.Errors.Should().HaveCount(1); + + const int minCharsInBase64 = SocialMediaAccount.MinPasswordCharsInBase64; + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be($"The field Password must be a string or array type with a minimum length of '{minCharsInBase64}'."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/password"); + } + + [Fact] + public async Task Cannot_exceed_max_length_constraint() + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + ModelStateValidationClient apiClient = new(httpClient); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + Password = Enumerable.Repeat((byte)'X', SocialMediaAccount.MaxPasswordChars + 1).ToArray() + } + } + }; + + // Act + Func action = () => apiClient.PostSocialMediaAccountAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync>()).Which.Result; + response.Errors.Should().HaveCount(1); + + const int maxCharsInBase64 = SocialMediaAccount.MaxPasswordCharsInBase64; + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be($"The field Password must be a string or array type with a maximum length of '{maxCharsInBase64}'."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/password"); + } + + [Theory] + [InlineData(-1)] + [InlineData(-0.56)] + [InlineData(123.98)] + [InlineData(124)] + public async Task Cannot_use_double_outside_of_valid_range(double age) + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + ModelStateValidationClient apiClient = new(httpClient); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + Age = age + } + } + }; + + // Act + Func action = () => apiClient.PostSocialMediaAccountAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync>()).Which.Result; + response.Errors.Should().HaveCount(1); + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be($"The field Age must be between {0.1} exclusive and {122.9} exclusive."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/age"); + } + + [Fact] + public async Task Cannot_use_relative_url() + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + ModelStateValidationClient apiClient = new(httpClient); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + BackgroundPicture = new Uri("relativeurl", UriKind.Relative) + } + } + }; + + // Act + Func action = () => apiClient.PostSocialMediaAccountAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync>()).Which.Result; + response.Errors.Should().HaveCount(1); + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be("The BackgroundPicture field is not a valid fully-qualified http, https, or ftp URL."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/backgroundPicture"); + } + + [Theory] + [InlineData(0)] + [InlineData(11)] + public async Task Cannot_exceed_collection_length_constraint(int length) + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + ModelStateValidationClient apiClient = new(httpClient); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + Tags = Enumerable.Repeat("-", length).ToList() + } + } + }; + + // Act + Func action = () => apiClient.PostSocialMediaAccountAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync>()).Which.Result; + response.Errors.Should().HaveCount(1); + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be("The field Tags must be a string or collection type with a minimum length of '1' and maximum length of '10'."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/tags"); + } + + [Fact] + public async Task Cannot_use_non_allowed_value() + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + ModelStateValidationClient apiClient = new(httpClient); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + CountryCode = "XX" + } + } + }; + + // Act + Func action = () => apiClient.PostSocialMediaAccountAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync>()).Which.Result; + response.Errors.Should().HaveCount(1); + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be("The CountryCode field does not equal any of the values specified in AllowedValuesAttribute."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/countryCode"); + } + + [Fact] + public async Task Cannot_use_denied_value() + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + ModelStateValidationClient apiClient = new(httpClient); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + Planet = "pluto" + } + } + }; + + // Act + Func action = () => apiClient.PostSocialMediaAccountAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync>()).Which.Result; + response.Errors.Should().HaveCount(1); + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be("The Planet field equals one of the values specified in DeniedValuesAttribute."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/planet"); + } + + [Fact] + public async Task Cannot_use_TimeSpan_outside_of_valid_range() + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + ModelStateValidationClient apiClient = new(httpClient); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + LastName = newAccount.LastName, + NextRevalidation = TimeSpan.FromSeconds(1).ToString() + } + } + }; + + // Act + Func action = () => apiClient.PostSocialMediaAccountAsync(requestBody); + + // Assert + ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync>()).Which.Result; + response.Errors.Should().HaveCount(1); + + ErrorObject errorObject = response.Errors.First(); + errorObject.Title.Should().Be("Input validation failed."); + errorObject.Detail.Should().Be("The field NextRevalidation must be between 01:00:00 and 05:00:00."); + errorObject.Source.Should().NotBeNull(); + errorObject.Source.Pointer.Should().Be("/data/attributes/nextRevalidation"); + } + + [Fact] + public async Task Can_create_resource_with_valid_properties() + { + // Arrange + SocialMediaAccount newAccount = _fakers.SocialMediaAccount.GenerateOne(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + ModelStateValidationClient apiClient = new(httpClient); + + var requestBody = new CreateSocialMediaAccountRequestDocument + { + Data = new DataInCreateSocialMediaAccountRequest + { + Attributes = new AttributesInCreateSocialMediaAccountRequest + { + AlternativeId = newAccount.AlternativeId, + FirstName = newAccount.FirstName, + LastName = newAccount.LastName, + UserName = newAccount.UserName, + CreditCard = newAccount.CreditCard, + Email = newAccount.Email, + Password = Convert.FromBase64String(newAccount.Password!), + Phone = newAccount.Phone, + Age = newAccount.Age, + ProfilePicture = newAccount.ProfilePicture, + BackgroundPicture = new Uri(newAccount.BackgroundPicture!), + Tags = newAccount.Tags, + CountryCode = newAccount.CountryCode, + Planet = newAccount.Planet, + NextRevalidation = newAccount.NextRevalidation!.Value.ToString(), + ValidatedAt = newAccount.ValidatedAt!, + ValidatedAtDate = new DateTimeOffset(newAccount.ValidatedAtDate!.Value.ToDateTime(new TimeOnly()), TimeSpan.Zero), + ValidatedAtTime = newAccount.ValidatedAtTime!.Value.ToTimeSpan() + } + } + }; + + // Act + Func action = () => apiClient.PostSocialMediaAccountAsync(requestBody); + + // Assert + await action.Should().NotThrowAsync(); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/ModelStateValidation/UtcDateTimeJsonConverter.cs b/test/OpenApiNSwagEndToEndTests/ModelStateValidation/UtcDateTimeJsonConverter.cs new file mode 100644 index 0000000000..c0c1d04ffb --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/ModelStateValidation/UtcDateTimeJsonConverter.cs @@ -0,0 +1,18 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace OpenApiNSwagEndToEndTests.ModelStateValidation; + +internal sealed class UtcDateTimeJsonConverter : JsonConverter +{ + public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + DateTimeOffset dateTimeOffset = DateTimeOffset.Parse(reader.GetString()!); + return dateTimeOffset.UtcDateTime; + } + + public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) + { + writer.WriteStringValue(value.ToUniversalTime().ToString("O")); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/OpenApiNSwagEndToEndTests.csproj b/test/OpenApiNSwagEndToEndTests/OpenApiNSwagEndToEndTests.csproj new file mode 100644 index 0000000000..2fc34289fa --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/OpenApiNSwagEndToEndTests.csproj @@ -0,0 +1,99 @@ + + + + net9.0 + + + + + + + + + + + + + + + + + + + + + + + internal + + + + + ClientIdGenerationModes + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs + + + ModelStateValidation + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs + + + Headers + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs + true + + + QueryStrings + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs + + + RestrictedControllers + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs + + + Links + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs + + + AtomicOperations + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs + + + OnlyRelationshipsInheritance + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs + + + SubsetOfVariousInheritance + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs + + + SubsetOfOperationsInheritance + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs + + + NoOperationsInheritance + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs + + + diff --git a/test/OpenApiNSwagEndToEndTests/QueryStrings/FilterTests.cs b/test/OpenApiNSwagEndToEndTests/QueryStrings/FilterTests.cs new file mode 100644 index 0000000000..f663d55180 --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/QueryStrings/FilterTests.cs @@ -0,0 +1,179 @@ +using System.Net; +using FluentAssertions; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using OpenApiNSwagEndToEndTests.QueryStrings.GeneratedCode; +using OpenApiTests; +using OpenApiTests.QueryStrings; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.QueryStrings; + +public sealed class FilterTests : IClassFixture, QueryStringDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, QueryStringDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly QueryStringFakers _fakers = new(); + + public FilterTests(IntegrationTestContext, QueryStringDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseController(); + } + + [Fact] + public async Task Can_filter_in_primary_resources() + { + // Arrange + List nodes = _fakers.Node.GenerateList(2); + nodes[0].Name = "John No Quote"; + nodes[1].Name = "Brian O'Quote"; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.AddRange(nodes); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new QueryStringsClient(httpClient); + + var queryString = new Dictionary + { + ["filter"] = "equals(name,'Brian O''Quote')" + }; + + // Act + NodeCollectionResponseDocument response = await apiClient.GetNodeCollectionAsync(queryString); + + // Assert + response.Data.Should().HaveCount(1); + response.Data.ElementAt(0).Id.Should().Be(nodes[1].StringId); + + response.Data.ElementAt(0).Attributes.RefShould().NotBeNull().And.Subject.With(attributes => + { + attributes.Name.Should().Be(nodes[1].Name); + attributes.Comment.Should().Be(nodes[1].Comment); + }); + + response.Meta.Should().NotBeNull(); + response.Meta.Should().ContainKey("total").WhoseValue.Should().Be(1); + } + + [Fact] + public async Task Can_filter_in_secondary_resources() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Children = _fakers.Node.GenerateSet(2); + node.Children.ElementAt(0).Comment = "Discount: $10"; + node.Children.ElementAt(1).Comment = "Discount: 5%"; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new QueryStringsClient(httpClient); + + var queryString = new Dictionary + { + ["filter"] = "and(startsWith(comment,'Discount:'),contains(comment,'%'))" + }; + + // Act + NodeCollectionResponseDocument response = await apiClient.GetNodeChildrenAsync(node.StringId!, queryString); + + // Assert + response.Data.Should().HaveCount(1); + response.Data.ElementAt(0).Id.Should().Be(node.Children.ElementAt(1).StringId); + + response.Data.ElementAt(0).Attributes.RefShould().NotBeNull().And.Subject.With(attributes => + { + attributes.Name.Should().Be(node.Children.ElementAt(1).Name); + attributes.Comment.Should().Be(node.Children.ElementAt(1).Comment); + }); + + response.Meta.Should().NotBeNull(); + response.Meta.Should().ContainKey("total").WhoseValue.Should().Be(1); + } + + [Fact] + public async Task Can_filter_at_ToMany_relationship_endpoint() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Children = _fakers.Node.GenerateSet(2); + node.Children.ElementAt(0).Children = _fakers.Node.GenerateSet(1); + node.Children.ElementAt(1).Children = _fakers.Node.GenerateSet(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new QueryStringsClient(httpClient); + + var queryString = new Dictionary + { + ["filter"] = "greaterThan(count(children),'1')" + }; + + // Act + NodeIdentifierCollectionResponseDocument response = await apiClient.GetNodeChildrenRelationshipAsync(node.StringId!, queryString); + + // Assert + response.Data.Should().HaveCount(1); + response.Data.ElementAt(0).Id.Should().Be(node.Children.ElementAt(1).StringId); + response.Meta.Should().NotBeNull(); + response.Meta.Should().ContainKey("total").WhoseValue.Should().Be(1); + response.Links.Should().NotBeNull(); + response.Links.Describedby.Should().Be("/swagger/v1/swagger.json"); + } + + [Fact] + public async Task Cannot_use_empty_filter() + { + // Arrange + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new QueryStringsClient(httpClient); + + var queryString = new Dictionary + { + ["filter"] = null + }; + + // Act + Func action = async () => _ = await apiClient.GetNodeAsync(Unknown.StringId.Int64, queryString); + + // Assert + ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; + exception.StatusCode.Should().Be((int)HttpStatusCode.BadRequest); + exception.Message.Should().Be("HTTP 400: The query string is invalid."); + exception.Result.Links.Should().NotBeNull(); + exception.Result.Links.Describedby.Should().Be("/swagger/v1/swagger.json"); + exception.Result.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Result.Errors.ElementAt(0); + error.Status.Should().Be("400"); + error.Title.Should().Be("Missing query string parameter value."); + error.Detail.Should().Be("Missing value for 'filter' query string parameter."); + error.Source.Should().NotBeNull(); + error.Source.Parameter.Should().Be("filter"); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/QueryStrings/IncludeTests.cs b/test/OpenApiNSwagEndToEndTests/QueryStrings/IncludeTests.cs new file mode 100644 index 0000000000..a7383e4fc0 --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/QueryStrings/IncludeTests.cs @@ -0,0 +1,201 @@ +using FluentAssertions; +using OpenApiNSwagEndToEndTests.QueryStrings.GeneratedCode; +using OpenApiTests; +using OpenApiTests.QueryStrings; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.QueryStrings; + +public sealed class IncludeTests : IClassFixture, QueryStringDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, QueryStringDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly QueryStringFakers _fakers = new(); + + public IncludeTests(IntegrationTestContext, QueryStringDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseController(); + testContext.UseController(); + } + + [Fact] + public async Task Can_include_in_primary_resources() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Values = _fakers.NameValuePair.GenerateList(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new QueryStringsClient(httpClient); + + var queryString = new Dictionary + { + ["include"] = "values.owner" + }; + + // Act + NodeCollectionResponseDocument response = await apiClient.GetNodeCollectionAsync(queryString); + + // Assert + response.Data.Should().HaveCount(1); + response.Data.ElementAt(0).Id.Should().Be(node.StringId); + + response.Included.Should().HaveCount(2); + response.Included.OfType().Should().ContainSingle(include => include.Id == node.Values.ElementAt(0).StringId); + response.Included.OfType().Should().ContainSingle(include => include.Id == node.Values.ElementAt(1).StringId); + } + + [Fact] + public async Task Can_include_in_primary_resource() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Values = _fakers.NameValuePair.GenerateList(1); + node.Children = _fakers.Node.GenerateSet(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new QueryStringsClient(httpClient); + + var queryString = new Dictionary + { + ["include"] = "children.parent,values" + }; + + // Act + PrimaryNodeResponseDocument response = await apiClient.GetNodeAsync(node.StringId!, queryString); + + // Assert + response.Data.Id.Should().Be(node.StringId); + + response.Included.Should().HaveCount(3); + response.Included.OfType().Should().ContainSingle(include => include.Id == node.Children.ElementAt(0).StringId); + response.Included.OfType().Should().ContainSingle(include => include.Id == node.Children.ElementAt(1).StringId); + response.Included.OfType().Should().ContainSingle(include => include.Id == node.Values[0].StringId); + } + + [Fact] + public async Task Can_include_in_secondary_resources() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Parent = _fakers.Node.GenerateOne(); + node.Values = _fakers.NameValuePair.GenerateList(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new QueryStringsClient(httpClient); + + var queryString = new Dictionary + { + ["include"] = "owner.parent,owner.values" + }; + + // Act + NameValuePairCollectionResponseDocument response = await apiClient.GetNodeValuesAsync(node.StringId!, queryString); + + // Assert + response.Data.Should().HaveCount(2); + + response.Included.Should().HaveCount(2); + response.Included.OfType().Should().ContainSingle(include => include.Id == node.StringId); + response.Included.OfType().Should().ContainSingle(include => include.Id == node.Parent.StringId); + } + + [Fact] + public async Task Can_include_in_secondary_resource() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Parent = _fakers.Node.GenerateOne(); + node.Parent.Parent = _fakers.Node.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new QueryStringsClient(httpClient); + + var queryString = new Dictionary + { + ["include"] = "parent.parent" + }; + + // Act + NullableSecondaryNodeResponseDocument response = await apiClient.GetNodeParentAsync(node.StringId!, queryString); + + // Assert + response.Data.Should().NotBeNull(); + response.Data.Id.Should().Be(node.Parent.StringId); + + response.Included.Should().HaveCount(1); + + response.Included.OfType().Should().ContainSingle(include => include.Id == node.Parent.Parent.StringId).Subject.With(include => + { + include.Attributes.Should().NotBeNull(); + include.Attributes.Name.Should().Be(node.Parent.Parent.Name); + }); + } + + [Fact] + public async Task Can_use_empty_include() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new QueryStringsClient(httpClient); + + var queryString = new Dictionary + { + ["include"] = null + }; + + // Act + PrimaryNodeResponseDocument response = await apiClient.GetNodeAsync(node.StringId!, queryString); + + // Assert + response.Data.Id.Should().Be(node.StringId); + + response.Included.Should().BeEmpty(); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/QueryStrings/PaginationTests.cs b/test/OpenApiNSwagEndToEndTests/QueryStrings/PaginationTests.cs new file mode 100644 index 0000000000..a78be7a19f --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/QueryStrings/PaginationTests.cs @@ -0,0 +1,188 @@ +using System.Net; +using FluentAssertions; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using OpenApiNSwagEndToEndTests.QueryStrings.GeneratedCode; +using OpenApiTests; +using OpenApiTests.QueryStrings; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.QueryStrings; + +public sealed class PaginationTests : IClassFixture, QueryStringDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, QueryStringDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly QueryStringFakers _fakers = new(); + + public PaginationTests(IntegrationTestContext, QueryStringDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseController(); + } + + [Fact] + public async Task Can_paginate_in_primary_resources() + { + // Arrange + List nodes = _fakers.Node.GenerateList(3); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.AddRange(nodes); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new QueryStringsClient(httpClient); + + var queryString = new Dictionary + { + ["page[size]"] = "1", + ["page[number]"] = "2" + }; + + // Act + NodeCollectionResponseDocument response = await apiClient.GetNodeCollectionAsync(queryString); + + // Assert + response.Data.Should().HaveCount(1); + response.Data.ElementAt(0).Id.Should().Be(nodes[1].StringId); + response.Meta.Should().NotBeNull(); + response.Meta.Should().ContainKey("total").WhoseValue.Should().Be(3); + } + + [Fact] + public async Task Can_paginate_in_secondary_resources() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Children = _fakers.Node.GenerateSet(3); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new QueryStringsClient(httpClient); + + var queryString = new Dictionary + { + ["page[size]"] = "2", + ["page[number]"] = "1" + }; + + // Act + NodeCollectionResponseDocument response = await apiClient.GetNodeChildrenAsync(node.StringId!, queryString); + + // Assert + response.Data.Should().HaveCount(2); + response.Data.ElementAt(0).Id.Should().Be(node.Children.ElementAt(0).StringId); + response.Data.ElementAt(1).Id.Should().Be(node.Children.ElementAt(1).StringId); + response.Meta.Should().NotBeNull(); + response.Meta.Should().ContainKey("total").WhoseValue.Should().Be(3); + } + + [Fact] + public async Task Can_paginate_at_ToMany_relationship_endpoint() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Children = _fakers.Node.GenerateSet(3); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new QueryStringsClient(httpClient); + + var queryString = new Dictionary + { + ["page[size]"] = "2", + ["page[number]"] = "2" + }; + + // Act + NodeIdentifierCollectionResponseDocument response = await apiClient.GetNodeChildrenRelationshipAsync(node.StringId!, queryString); + + // Assert + response.Data.Should().HaveCount(1); + response.Data.ElementAt(0).Id.Should().Be(node.Children.ElementAt(2).StringId); + response.Meta.Should().NotBeNull(); + response.Meta.Should().ContainKey("total").WhoseValue.Should().Be(3); + } + + [Fact] + public async Task Cannot_use_empty_page_size() + { + // Arrange + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new QueryStringsClient(httpClient); + + var queryString = new Dictionary + { + ["page[size]"] = null + }; + + // Act + Func action = async () => _ = await apiClient.GetNodeAsync(Unknown.StringId.Int64, queryString); + + // Assert + ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; + exception.StatusCode.Should().Be((int)HttpStatusCode.BadRequest); + exception.Message.Should().Be("HTTP 400: The query string is invalid."); + exception.Result.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Result.Errors.ElementAt(0); + error.Status.Should().Be("400"); + error.Title.Should().Be("Missing query string parameter value."); + error.Detail.Should().Be("Missing value for 'page[size]' query string parameter."); + error.Source.Should().NotBeNull(); + error.Source.Parameter.Should().Be("page[size]"); + } + + [Fact] + public async Task Cannot_use_empty_page_number() + { + // Arrange + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new QueryStringsClient(httpClient); + + var queryString = new Dictionary + { + ["page[number]"] = null + }; + + // Act + Func action = async () => _ = await apiClient.GetNodeAsync(Unknown.StringId.Int64, queryString); + + // Assert + ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; + exception.StatusCode.Should().Be((int)HttpStatusCode.BadRequest); + exception.Message.Should().Be("HTTP 400: The query string is invalid."); + exception.Result.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Result.Errors.ElementAt(0); + error.Status.Should().Be("400"); + error.Title.Should().Be("Missing query string parameter value."); + error.Detail.Should().Be("Missing value for 'page[number]' query string parameter."); + error.Source.Should().NotBeNull(); + error.Source.Parameter.Should().Be("page[number]"); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/QueryStrings/SortTests.cs b/test/OpenApiNSwagEndToEndTests/QueryStrings/SortTests.cs new file mode 100644 index 0000000000..44a11b217f --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/QueryStrings/SortTests.cs @@ -0,0 +1,158 @@ +using System.Net; +using FluentAssertions; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using OpenApiNSwagEndToEndTests.QueryStrings.GeneratedCode; +using OpenApiTests; +using OpenApiTests.QueryStrings; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.QueryStrings; + +public sealed class SortTests : IClassFixture, QueryStringDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, QueryStringDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly QueryStringFakers _fakers = new(); + + public SortTests(IntegrationTestContext, QueryStringDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseController(); + } + + [Fact] + public async Task Can_sort_in_primary_resources() + { + // Arrange + List nodes = _fakers.Node.GenerateList(2); + nodes[0].Name = "A"; + nodes[1].Name = "B"; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.AddRange(nodes); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new QueryStringsClient(httpClient); + + var queryString = new Dictionary + { + ["sort"] = "-name" + }; + + // Act + NodeCollectionResponseDocument response = await apiClient.GetNodeCollectionAsync(queryString); + + // Assert + response.Data.Should().HaveCount(2); + response.Data.ElementAt(0).Id.Should().Be(nodes[1].StringId); + response.Data.ElementAt(1).Id.Should().Be(nodes[0].StringId); + } + + [Fact] + public async Task Can_sort_in_secondary_resources() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Children = _fakers.Node.GenerateSet(2); + node.Children.ElementAt(0).Name = "B"; + node.Children.ElementAt(1).Name = "A"; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new QueryStringsClient(httpClient); + + var queryString = new Dictionary + { + ["sort"] = "name" + }; + + // Act + NodeCollectionResponseDocument response = await apiClient.GetNodeChildrenAsync(node.StringId!, queryString); + + // Assert + response.Data.Should().HaveCount(2); + response.Data.ElementAt(0).Id.Should().Be(node.Children.ElementAt(1).StringId); + response.Data.ElementAt(1).Id.Should().Be(node.Children.ElementAt(0).StringId); + } + + [Fact] + public async Task Can_sort_at_ToMany_relationship_endpoint() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Children = _fakers.Node.GenerateSet(2); + node.Children.ElementAt(0).Children = _fakers.Node.GenerateSet(1); + node.Children.ElementAt(1).Children = _fakers.Node.GenerateSet(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new QueryStringsClient(httpClient); + + var queryString = new Dictionary + { + ["sort"] = "count(children)" + }; + + // Act + NodeIdentifierCollectionResponseDocument response = await apiClient.GetNodeChildrenRelationshipAsync(node.StringId!, queryString); + + // Assert + response.Data.Should().HaveCount(2); + response.Data.ElementAt(0).Id.Should().Be(node.Children.ElementAt(0).StringId); + response.Data.ElementAt(1).Id.Should().Be(node.Children.ElementAt(1).StringId); + } + + [Fact] + public async Task Cannot_use_empty_sort() + { + // Arrange + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new QueryStringsClient(httpClient); + + var queryString = new Dictionary + { + ["sort"] = null + }; + + // Act + Func action = async () => _ = await apiClient.GetNodeAsync(Unknown.StringId.Int64, queryString); + + // Assert + ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; + exception.StatusCode.Should().Be((int)HttpStatusCode.BadRequest); + exception.Message.Should().Be("HTTP 400: The query string is invalid."); + exception.Result.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Result.Errors.ElementAt(0); + error.Status.Should().Be("400"); + error.Title.Should().Be("Missing query string parameter value."); + error.Detail.Should().Be("Missing value for 'sort' query string parameter."); + error.Source.Should().NotBeNull(); + error.Source.Parameter.Should().Be("sort"); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/QueryStrings/SparseFieldSetTests.cs b/test/OpenApiNSwagEndToEndTests/QueryStrings/SparseFieldSetTests.cs new file mode 100644 index 0000000000..ccd6e77bcc --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/QueryStrings/SparseFieldSetTests.cs @@ -0,0 +1,205 @@ +using FluentAssertions; +using OpenApiNSwagEndToEndTests.QueryStrings.GeneratedCode; +using OpenApiTests; +using OpenApiTests.QueryStrings; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.QueryStrings; + +public sealed class SparseFieldSetTests : IClassFixture, QueryStringDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, QueryStringDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly QueryStringFakers _fakers = new(); + + public SparseFieldSetTests(IntegrationTestContext, QueryStringDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseController(); + } + + [Fact] + public async Task Can_select_attribute_in_primary_resources() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new QueryStringsClient(httpClient); + + var queryString = new Dictionary + { + ["fields[nodes]"] = "name" + }; + + // Act + NodeCollectionResponseDocument response = await apiClient.GetNodeCollectionAsync(queryString); + + // Assert + response.Data.Should().HaveCount(1); + response.Data.ElementAt(0).Id.Should().Be(node.StringId); + + response.Data.ElementAt(0).Attributes.RefShould().NotBeNull().And.Subject.With(attributes => + { + attributes.Name.Should().Be(node.Name); + attributes.Comment.Should().BeNull(); + }); + + response.Data.ElementAt(0).Relationships.Should().BeNull(); + } + + [Fact] + public async Task Can_select_fields_in_primary_resource() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new QueryStringsClient(httpClient); + + var queryString = new Dictionary + { + ["fields[nodes]"] = "comment,parent" + }; + + // Act + PrimaryNodeResponseDocument response = await apiClient.GetNodeAsync(node.StringId!, queryString); + + // Assert + response.Data.Id.Should().Be(node.StringId); + response.Data.Attributes.Should().NotBeNull(); + response.Data.Attributes.Name.Should().BeNull(); + response.Data.Attributes.Comment.Should().Be(node.Comment); + response.Data.Relationships.Should().NotBeNull(); + response.Data.Relationships.Parent.Should().NotBeNull(); + response.Data.Relationships.Children.Should().BeNull(); + } + + [Fact] + public async Task Can_select_fields_in_secondary_resources() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Children = _fakers.Node.GenerateSet(1); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new QueryStringsClient(httpClient); + + var queryString = new Dictionary + { + ["fields[nodes]"] = "comment,children" + }; + + // Act + NodeCollectionResponseDocument response = await apiClient.GetNodeChildrenAsync(node.StringId!, queryString); + + // Assert + response.Data.Should().HaveCount(1); + response.Data.ElementAt(0).Id.Should().Be(node.Children.ElementAt(0).StringId); + + response.Data.ElementAt(0).Attributes.RefShould().NotBeNull().And.Subject.With(attributes => + { + attributes.Name.Should().BeNull(); + attributes.Comment.Should().Be(node.Children.ElementAt(0).Comment); + }); + + response.Data.ElementAt(0).Relationships.RefShould().NotBeNull().And.Subject.With(relationships => + { + relationships.Parent.Should().BeNull(); + relationships.Children.Should().NotBeNull(); + }); + } + + [Fact] + public async Task Can_select_fields_in_secondary_resource() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + node.Parent = _fakers.Node.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new QueryStringsClient(httpClient); + + var queryString = new Dictionary + { + ["fields[nodes]"] = "comment,children" + }; + + // Act + NullableSecondaryNodeResponseDocument response = await apiClient.GetNodeParentAsync(node.StringId!, queryString); + + // Assert + response.Data.Should().NotBeNull(); + response.Data.Id.Should().Be(node.Parent.StringId); + response.Data.Attributes.Should().NotBeNull(); + response.Data.Attributes.Name.Should().BeNull(); + response.Data.Attributes.Comment.Should().Be(node.Parent.Comment); + response.Data.Relationships.Should().NotBeNull(); + response.Data.Relationships.Parent.Should().BeNull(); + response.Data.Relationships.Children.Should().NotBeNull(); + } + + [Fact] + public async Task Can_select_empty_fieldset() + { + // Arrange + Node node = _fakers.Node.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Nodes.Add(node); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new QueryStringsClient(httpClient); + + var queryString = new Dictionary + { + ["fields[nodes]"] = null + }; + + // Act + PrimaryNodeResponseDocument response = await apiClient.GetNodeAsync(node.StringId!, queryString); + + // Assert + response.Data.Id.Should().Be(node.StringId); + response.Data.Attributes.Should().BeNull(); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/ResourceInheritance/NoOperations/ResourceInheritanceTests.cs b/test/OpenApiNSwagEndToEndTests/ResourceInheritance/NoOperations/ResourceInheritanceTests.cs new file mode 100644 index 0000000000..7f6dcbbaaf --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/ResourceInheritance/NoOperations/ResourceInheritanceTests.cs @@ -0,0 +1,951 @@ +using FluentAssertions; +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using JsonApiDotNetCore.Resources; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using OpenApiNSwagEndToEndTests.NoOperationsInheritance.GeneratedCode; +using OpenApiTests; +using OpenApiTests.ResourceInheritance; +using OpenApiTests.ResourceInheritance.Models; +using OpenApiTests.ResourceInheritance.NoOperations; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.ResourceInheritance.NoOperations; + +public sealed class ResourceInheritanceTests + : IClassFixture, ResourceInheritanceDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, ResourceInheritanceDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly ResourceInheritanceFakers _fakers = new(); + + public ResourceInheritanceTests(IntegrationTestContext, ResourceInheritanceDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseInheritanceControllers(false); + + testContext.ConfigureServices(services => + { + services.AddScoped(typeof(IResourceChangeTracker<>), typeof(NeverSameResourceChangeTracker<>)); + + services.AddSingleton(); + services.AddSingleton(); + }); + } + + [Fact] + public async Task Can_get_primary_resources_at_abstract_endpoint() + { + // Arrange + Residence residence = _fakers.Residence.GenerateOne(); + Mansion mansion = _fakers.Mansion.GenerateOne(); + FamilyHome familyHome = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Buildings.AddRange(residence, mansion, familyHome); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new NoOperationsInheritanceClient(httpClient); + + // Act + BuildingCollectionResponseDocument response = await apiClient.GetBuildingCollectionAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(3); + + response.Data.OfType().Should().ContainSingle(data => data.Id == residence.StringId).Subject.With(data => + { + AttributesInResidenceResponse attributes = data.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(residence.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(residence.NumberOfResidents); + + RelationshipsInResidenceResponse relationships = data.Relationships.Should().BeOfType().Subject; + + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().BeNull(); + }); + + response.Data.OfType().Should().ContainSingle(data => data.Id == mansion.StringId).Subject.With(data => + { + AttributesInMansionResponse attributes = data.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(mansion.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(mansion.NumberOfResidents); + attributes.OwnerName.Should().Be(mansion.OwnerName); + + RelationshipsInMansionResponse relationships = data.Relationships.Should().BeOfType().Subject; + + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().BeNull(); + + relationships.Staff.Should().NotBeNull(); + relationships.Staff.Data.Should().BeNull(); + }); + + response.Data.OfType().Should().ContainSingle(data => data.Id == familyHome.StringId).Subject.With(data => + { + AttributesInFamilyHomeResponse attributes = data.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(familyHome.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(familyHome.NumberOfResidents); + attributes.FloorCount.Should().Be(familyHome.FloorCount); + + RelationshipsInFamilyHomeResponse relationships = data.Relationships.Should().BeOfType().Subject; + + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().BeNull(); + }); + } + + [Fact] + public async Task Can_get_primary_resources_at_concrete_base_endpoint() + { + // Arrange + Road road = _fakers.Road.GenerateOne(); + CyclePath cyclePath = _fakers.CyclePath.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Roads.AddRange(road, cyclePath); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new NoOperationsInheritanceClient(httpClient); + + // Act + RoadCollectionResponseDocument response = await apiClient.GetRoadCollectionAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(2); + + response.Data.Should().ContainSingle(data => data.Id == road.StringId).Subject.With(data => + { + AttributesInRoadResponse? attributes = data.Attributes.Should().BeOfType().Subject; + + ((decimal?)attributes.LengthInMeters).Should().BeApproximately(road.LengthInMeters); + + data.Relationships.Should().BeNull(); + }); + + response.Data.OfType().Should().ContainSingle(data => data.Id == cyclePath.StringId).Subject.With(data => + { + AttributesInCyclePathResponse attributes = data.Attributes.Should().BeOfType().Subject; + + ((decimal?)attributes.LengthInMeters).Should().BeApproximately(cyclePath.LengthInMeters); + attributes.HasLaneForPedestrians.Should().Be(cyclePath.HasLaneForPedestrians); + + data.Relationships.Should().BeNull(); + }); + } + + [Fact] + public async Task Can_get_primary_resources_at_concrete_derived_endpoint() + { + // Arrange + FamilyHome familyHome1 = _fakers.FamilyHome.GenerateOne(); + FamilyHome familyHome2 = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.Buildings.AddRange(familyHome1, familyHome2); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new NoOperationsInheritanceClient(httpClient); + + // Act + FamilyHomeCollectionResponseDocument response = await apiClient.GetFamilyHomeCollectionAsync(); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(2); + + response.Data.Should().ContainSingle(data => data.Id == familyHome1.StringId).Subject.With(data => + { + AttributesInResidenceResponse attributes = data.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(familyHome1.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(familyHome1.NumberOfResidents); + + RelationshipsInResidenceResponse relationships = data.Relationships.Should().BeOfType().Subject; + + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().BeNull(); + }); + + response.Data.Should().ContainSingle(data => data.Id == familyHome2.StringId).Subject.With(data => + { + AttributesInResidenceResponse attributes = data.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(familyHome2.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(familyHome2.NumberOfResidents); + + RelationshipsInResidenceResponse relationships = data.Relationships.Should().BeOfType().Subject; + + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().BeNull(); + }); + } + + [Fact] + public async Task Can_get_primary_resource_at_abstract_endpoint() + { + // Arrange + Mansion mansion = _fakers.Mansion.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Buildings.Add(mansion); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new NoOperationsInheritanceClient(httpClient); + + // Act + PrimaryBuildingResponseDocument response = await apiClient.GetBuildingAsync(mansion.StringId!); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().BeOfType(); + response.Data.Id.Should().Be(mansion.StringId); + + response.Data.Attributes.Should().BeOfType().Subject.With(attributes => + { + attributes.SurfaceInSquareMeters.Should().Be(mansion.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(mansion.NumberOfResidents); + attributes.OwnerName.Should().Be(mansion.OwnerName); + }); + + response.Data.Relationships.Should().BeOfType().Subject.With(relationships => + { + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().BeNull(); + + relationships.Staff.Should().NotBeNull(); + relationships.Staff.Data.Should().BeNull(); + }); + } + + [Fact] + public async Task Can_get_primary_resource_at_concrete_base_endpoint() + { + // Arrange + CyclePath cyclePath = _fakers.CyclePath.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Roads.Add(cyclePath); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new NoOperationsInheritanceClient(httpClient); + + // Act + PrimaryRoadResponseDocument response = await apiClient.GetRoadAsync(cyclePath.StringId!); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().BeOfType(); + response.Data.Id.Should().Be(cyclePath.StringId); + + response.Data.Attributes.Should().BeOfType().Subject.With(attributes => + { + ((decimal?)attributes.LengthInMeters).Should().BeApproximately(cyclePath.LengthInMeters); + attributes.HasLaneForPedestrians.Should().Be(cyclePath.HasLaneForPedestrians); + }); + + response.Data.Relationships.Should().BeNull(); + } + + [Fact] + public async Task Can_get_primary_resource_at_concrete_derived_endpoint() + { + // Arrange + FamilyHome familyHome = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Buildings.Add(familyHome); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new NoOperationsInheritanceClient(httpClient); + + // Act + PrimaryFamilyHomeResponseDocument response = await apiClient.GetFamilyHomeAsync(familyHome.StringId!); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().BeOfType(); + response.Data.Id.Should().Be(familyHome.StringId); + + response.Data.Attributes.Should().BeOfType().Subject.With(attributes => + { + attributes.SurfaceInSquareMeters.Should().Be(familyHome.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(familyHome.NumberOfResidents); + }); + + response.Data.Relationships.Should().BeOfType().Subject.With(relationships => + { + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().BeNull(); + }); + } + + [Fact] + public async Task Can_get_secondary_resource_at_abstract_base_endpoint() + { + // Arrange + Bedroom bedroom = _fakers.Bedroom.GenerateOne(); + FamilyHome familyHome = _fakers.FamilyHome.GenerateOne(); + bedroom.Residence = familyHome; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Rooms.Add(bedroom); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new NoOperationsInheritanceClient(httpClient); + + // Act + SecondaryResidenceResponseDocument response = await apiClient.GetRoomResidenceAsync(bedroom.StringId!); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().BeOfType(); + response.Data.Id.Should().Be(bedroom.Residence.StringId); + + response.Data.Attributes.Should().BeOfType().Subject.With(attributes => + { + attributes.SurfaceInSquareMeters.Should().Be(familyHome.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(familyHome.NumberOfResidents); + attributes.FloorCount.Should().Be(familyHome.FloorCount); + }); + + response.Data.Relationships.Should().BeOfType().Subject.With(relationships => + { + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().BeNull(); + }); + } + + [Fact] + public async Task Can_get_secondary_resource_at_concrete_derived_endpoint() + { + // Arrange + Bedroom bedroom = _fakers.Bedroom.GenerateOne(); + FamilyHome familyHome = _fakers.FamilyHome.GenerateOne(); + bedroom.Residence = familyHome; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Rooms.Add(bedroom); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new NoOperationsInheritanceClient(httpClient); + + // Act + SecondaryResidenceResponseDocument response = await apiClient.GetBedroomResidenceAsync(bedroom.StringId!); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().BeOfType(); + response.Data.Id.Should().Be(bedroom.Residence.StringId); + + response.Data.Attributes.Should().BeOfType().Subject.With(attributes => + { + attributes.SurfaceInSquareMeters.Should().Be(familyHome.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(familyHome.NumberOfResidents); + attributes.FloorCount.Should().Be(familyHome.FloorCount); + }); + + response.Data.Relationships.Should().BeOfType().Subject.With(relationships => + { + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().BeNull(); + }); + } + + [Fact] + public async Task Can_get_secondary_resources_at_concrete_base_endpoint() + { + // Arrange + Kitchen kitchen = _fakers.Kitchen.GenerateOne(); + Bedroom bedroom = _fakers.Bedroom.GenerateOne(); + + FamilyHome familyHome = _fakers.FamilyHome.GenerateOne(); + familyHome.Rooms.Add(kitchen); + familyHome.Rooms.Add(bedroom); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.FamilyHomes.Add(familyHome); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new NoOperationsInheritanceClient(httpClient); + + // Act + RoomCollectionResponseDocument response = await apiClient.GetResidenceRoomsAsync(familyHome.StringId!); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(2); + + response.Data.OfType().Should().ContainSingle(data => data.Id == kitchen.StringId).Subject.With(data => + { + AttributesInKitchenResponse attributes = data.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(kitchen.SurfaceInSquareMeters); + attributes.HasPantry.Should().Be(kitchen.HasPantry); + + RelationshipsInKitchenResponse relationships = data.Relationships.Should().BeOfType().Subject; + + relationships.Residence.Should().NotBeNull(); + relationships.Residence.Data.Should().BeNull(); + }); + + response.Data.OfType().Should().ContainSingle(data => data.Id == bedroom.StringId).Subject.With(data => + { + AttributesInBedroomResponse attributes = data.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(bedroom.SurfaceInSquareMeters); + attributes.BedCount.Should().Be(bedroom.BedCount); + + RelationshipsInBedroomResponse relationships = data.Relationships.Should().BeOfType().Subject; + + relationships.Residence.Should().NotBeNull(); + relationships.Residence.Data.Should().BeNull(); + }); + } + + [Fact] + public async Task Can_get_secondary_resources_at_concrete_derived_endpoint() + { + // Arrange + Bathroom bathroom = _fakers.Bathroom.GenerateOne(); + Toilet toilet = _fakers.Toilet.GenerateOne(); + + Mansion mansion = _fakers.Mansion.GenerateOne(); + mansion.Rooms.Add(bathroom); + mansion.Rooms.Add(toilet); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(mansion); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new NoOperationsInheritanceClient(httpClient); + + // Act + RoomCollectionResponseDocument response = await apiClient.GetMansionRoomsAsync(mansion.StringId!); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(2); + + response.Data.OfType().Should().ContainSingle(data => data.Id == bathroom.StringId).Subject.With(data => + { + AttributesInBathroomResponse attributes = data.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(bathroom.SurfaceInSquareMeters); + attributes.HasBath.Should().Be(bathroom.HasBath); + + RelationshipsInBathroomResponse relationships = data.Relationships.Should().BeOfType().Subject; + + relationships.Residence.Should().NotBeNull(); + relationships.Residence.Data.Should().BeNull(); + }); + + response.Data.OfType().Should().ContainSingle(data => data.Id == toilet.StringId).Subject.With(data => + { + AttributesInToiletResponse attributes = data.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(toilet.SurfaceInSquareMeters); + attributes.HasSink.Should().Be(toilet.HasSink); + + RelationshipsInToiletResponse relationships = data.Relationships.Should().BeOfType().Subject; + + relationships.Residence.Should().NotBeNull(); + relationships.Residence.Data.Should().BeNull(); + }); + } + + [Fact] + public async Task Can_create_concrete_base_resource_at_abstract_endpoint() + { + // Arrange + double newLengthInMeters = (double)_fakers.Road.GenerateOne().LengthInMeters; + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new NoOperationsInheritanceClient(httpClient); + + CreateRoadRequestDocument requestBody = new() + { + Data = new DataInCreateRoadRequest + { + Attributes = new AttributesInCreateRoadRequest + { + LengthInMeters = newLengthInMeters + } + } + }; + + // Act + PrimaryRoadResponseDocument? response = await ApiResponse.TranslateAsync(async () => await apiClient.PostRoadAsync(requestBody)); + + // Assert + response.Should().NotBeNull(); + + DataInRoadResponse roadData = response.Data.Should().BeOfType().Subject; + + AttributesInRoadResponse roadAttributes = roadData.Attributes.Should().BeOfType().Subject; + roadAttributes.LengthInMeters.Should().Be(newLengthInMeters); + + roadData.Relationships.Should().BeNull(); + + long newRoadId = long.Parse(roadData.Id.Should().NotBeNull().And.Subject); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Road roadInDatabase = await dbContext.Roads.FirstWithIdAsync(newRoadId); + + roadInDatabase.LengthInMeters.Should().Be((decimal)newLengthInMeters); + }); + } + + [Fact] + public async Task Can_create_concrete_derived_resource_at_abstract_endpoint_with_relationships_and_includes() + { + // Arrange + Bedroom existingBedroom1 = _fakers.Bedroom.GenerateOne(); + Bedroom existingBedroom2 = _fakers.Bedroom.GenerateOne(); + LivingRoom existingLivingRoom = _fakers.LivingRoom.GenerateOne(); + + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + existingMansion.Rooms.Add(existingBedroom1); + existingMansion.Rooms.Add(existingBedroom2); + existingMansion.Rooms.Add(existingLivingRoom); + + FamilyHome newFamilyHome = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new NoOperationsInheritanceClient(httpClient); + + CreateBuildingRequestDocument requestBody = new() + { + Data = new DataInCreateFamilyHomeRequest + { + Attributes = new AttributesInCreateFamilyHomeRequest + { + SurfaceInSquareMeters = newFamilyHome.SurfaceInSquareMeters!.Value, + NumberOfResidents = newFamilyHome.NumberOfResidents!.Value, + FloorCount = newFamilyHome.FloorCount + }, + Relationships = new RelationshipsInCreateFamilyHomeRequest + { + Rooms = new ToManyRoomInRequest + { + Data = + [ + new BedroomIdentifierInRequest + { + Id = existingBedroom1.StringId! + }, + new BedroomIdentifierInRequest + { + Id = existingBedroom2.StringId! + }, + new LivingRoomIdentifierInRequest + { + Id = existingLivingRoom.StringId! + } + ] + } + } + } + }; + + var queryString = new Dictionary + { + ["include"] = "rooms" + }; + + // Act + PrimaryBuildingResponseDocument? response = await ApiResponse.TranslateAsync(async () => await apiClient.PostBuildingAsync(requestBody, queryString)); + + // Assert + response.Should().NotBeNull(); + + DataInFamilyHomeResponse familyHomeData = response.Data.Should().BeOfType().Subject; + + AttributesInFamilyHomeResponse familyHomeAttributes = familyHomeData.Attributes.Should().BeOfType().Subject; + familyHomeAttributes.SurfaceInSquareMeters.Should().Be(newFamilyHome.SurfaceInSquareMeters); + familyHomeAttributes.NumberOfResidents.Should().Be(newFamilyHome.NumberOfResidents); + familyHomeAttributes.FloorCount.Should().Be(newFamilyHome.FloorCount); + + RelationshipsInFamilyHomeResponse familyHomeRelationships = familyHomeData.Relationships.Should().BeOfType().Subject; + + familyHomeRelationships.Rooms.RefShould().NotBeNull().And.Subject.Data.With(roomData => + { + roomData.Should().HaveCount(3); + roomData.OfType().Should().ContainSingle(data => data.Id == existingBedroom1.StringId); + roomData.OfType().Should().ContainSingle(data => data.Id == existingBedroom2.StringId); + roomData.OfType().Should().ContainSingle(data => data.Id == existingLivingRoom.StringId); + }); + + long newFamilyHomeId = long.Parse(familyHomeData.Id.Should().NotBeNull().And.Subject); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + FamilyHome familyHomeInDatabase = await dbContext.FamilyHomes.Include(familyHome => familyHome.Rooms).FirstWithIdAsync(newFamilyHomeId); + + familyHomeInDatabase.SurfaceInSquareMeters.Should().Be(newFamilyHome.SurfaceInSquareMeters); + familyHomeInDatabase.NumberOfResidents.Should().Be(newFamilyHome.NumberOfResidents); + familyHomeInDatabase.FloorCount.Should().Be(newFamilyHome.FloorCount); + + familyHomeInDatabase.Rooms.Should().HaveCount(3); + familyHomeInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom1.Id); + familyHomeInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom2.Id); + familyHomeInDatabase.Rooms.OfType().Should().ContainSingle(livingRoom => livingRoom.Id == existingLivingRoom.Id); + }); + } + + [Fact] + public async Task Can_create_concrete_derived_resource_at_concrete_base_endpoint() + { + // Arrange + FamilyHome newFamilyHome = _fakers.FamilyHome.GenerateOne(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new NoOperationsInheritanceClient(httpClient); + + CreateResidenceRequestDocument requestBody = new() + { + Data = new DataInCreateFamilyHomeRequest + { + Attributes = new AttributesInCreateFamilyHomeRequest + { + SurfaceInSquareMeters = newFamilyHome.SurfaceInSquareMeters!.Value, + NumberOfResidents = newFamilyHome.NumberOfResidents!.Value, + FloorCount = newFamilyHome.FloorCount + } + } + }; + + // Act + PrimaryResidenceResponseDocument? response = await ApiResponse.TranslateAsync(async () => await apiClient.PostResidenceAsync(requestBody)); + + // Assert + response.Should().NotBeNull(); + + DataInFamilyHomeResponse familyHomeData = response.Data.Should().BeOfType().Subject; + + AttributesInFamilyHomeResponse familyHomeAttributes = familyHomeData.Attributes.Should().BeOfType().Subject; + familyHomeAttributes.SurfaceInSquareMeters.Should().Be(newFamilyHome.SurfaceInSquareMeters); + familyHomeAttributes.NumberOfResidents.Should().Be(newFamilyHome.NumberOfResidents); + familyHomeAttributes.FloorCount.Should().Be(newFamilyHome.FloorCount); + + RelationshipsInFamilyHomeResponse familyHomeRelationships = familyHomeData.Relationships.Should().BeOfType().Subject; + familyHomeRelationships.Rooms.Should().NotBeNull(); + + long newFamilyHomeId = long.Parse(familyHomeData.Id.Should().NotBeNull().And.Subject); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + FamilyHome familyHomeInDatabase = await dbContext.FamilyHomes.Include(familyHome => familyHome.Rooms).FirstWithIdAsync(newFamilyHomeId); + + familyHomeInDatabase.SurfaceInSquareMeters.Should().Be(newFamilyHome.SurfaceInSquareMeters); + familyHomeInDatabase.NumberOfResidents.Should().Be(newFamilyHome.NumberOfResidents); + familyHomeInDatabase.FloorCount.Should().Be(newFamilyHome.FloorCount); + + familyHomeInDatabase.Rooms.Should().BeEmpty(); + }); + } + + [Fact] + public async Task Can_update_concrete_base_resource_at_abstract_endpoint() + { + // Arrange + Road existingRoad = _fakers.Road.GenerateOne(); + + double newLengthInMeters = (double)_fakers.Road.GenerateOne().LengthInMeters; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Roads.Add(existingRoad); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new NoOperationsInheritanceClient(httpClient); + + UpdateRoadRequestDocument requestBody = new() + { + Data = new DataInUpdateRoadRequest + { + Id = existingRoad.StringId!, + Attributes = new AttributesInUpdateRoadRequest + { + LengthInMeters = newLengthInMeters + } + } + }; + + // Act + PrimaryRoadResponseDocument? response = + await ApiResponse.TranslateAsync(async () => await apiClient.PatchRoadAsync(existingRoad.StringId!, requestBody)); + + // Assert + response.Should().NotBeNull(); + + DataInRoadResponse roadData = response.Data.Should().BeOfType().Subject; + + AttributesInRoadResponse roadAttributes = roadData.Attributes.Should().BeOfType().Subject; + roadAttributes.LengthInMeters.Should().Be(newLengthInMeters); + + roadData.Relationships.Should().BeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Road roadInDatabase = await dbContext.Roads.FirstWithIdAsync(existingRoad.Id); + + roadInDatabase.LengthInMeters.Should().Be((decimal)newLengthInMeters); + }); + } + + [Fact] + public async Task Can_update_concrete_derived_resource_at_abstract_endpoint_with_relationships_and_includes() + { + // Arrange + Bedroom existingBedroom1 = _fakers.Bedroom.GenerateOne(); + Bedroom existingBedroom2 = _fakers.Bedroom.GenerateOne(); + LivingRoom existingLivingRoom = _fakers.LivingRoom.GenerateOne(); + + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + existingMansion.Rooms.Add(existingBedroom1); + existingMansion.Rooms.Add(existingBedroom2); + existingMansion.Rooms.Add(existingLivingRoom); + + FamilyHome existingFamilyHome = _fakers.FamilyHome.GenerateOne(); + existingFamilyHome.Rooms.Add(_fakers.Kitchen.GenerateOne()); + + FamilyHome newFamilyHome = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + dbContext.FamilyHomes.Add(existingFamilyHome); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new NoOperationsInheritanceClient(httpClient); + + UpdateBuildingRequestDocument requestBody = new() + { + Data = new DataInUpdateFamilyHomeRequest + { + Id = existingFamilyHome.StringId!, + Attributes = new AttributesInUpdateFamilyHomeRequest + { + SurfaceInSquareMeters = newFamilyHome.SurfaceInSquareMeters!.Value, + NumberOfResidents = newFamilyHome.NumberOfResidents!.Value, + FloorCount = newFamilyHome.FloorCount + }, + Relationships = new RelationshipsInUpdateFamilyHomeRequest + { + Rooms = new ToManyRoomInRequest + { + Data = + [ + new BedroomIdentifierInRequest + { + Id = existingBedroom1.StringId! + }, + new BedroomIdentifierInRequest + { + Id = existingBedroom2.StringId! + }, + new LivingRoomIdentifierInRequest + { + Id = existingLivingRoom.StringId! + } + ] + } + } + } + }; + + var queryString = new Dictionary + { + ["include"] = "rooms" + }; + + // Act + PrimaryBuildingResponseDocument? response = + await ApiResponse.TranslateAsync(async () => await apiClient.PatchBuildingAsync(existingFamilyHome.StringId!, requestBody, queryString)); + + // Assert + response.Should().NotBeNull(); + + DataInFamilyHomeResponse familyHomeData = response.Data.Should().BeOfType().Subject; + + AttributesInFamilyHomeResponse familyHomeAttributes = familyHomeData.Attributes.Should().BeOfType().Subject; + familyHomeAttributes.SurfaceInSquareMeters.Should().Be(newFamilyHome.SurfaceInSquareMeters); + familyHomeAttributes.NumberOfResidents.Should().Be(newFamilyHome.NumberOfResidents); + familyHomeAttributes.FloorCount.Should().Be(newFamilyHome.FloorCount); + + RelationshipsInFamilyHomeResponse familyHomeRelationships = familyHomeData.Relationships.Should().BeOfType().Subject; + + familyHomeRelationships.Rooms.RefShould().NotBeNull().And.Subject.Data.With(roomData => + { + roomData.Should().HaveCount(3); + roomData.OfType().Should().ContainSingle(data => data.Id == existingBedroom1.StringId); + roomData.OfType().Should().ContainSingle(data => data.Id == existingBedroom2.StringId); + roomData.OfType().Should().ContainSingle(data => data.Id == existingLivingRoom.StringId); + }); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + FamilyHome familyHomeInDatabase = await dbContext.FamilyHomes.Include(familyHome => familyHome.Rooms).FirstWithIdAsync(existingFamilyHome.Id); + + familyHomeInDatabase.SurfaceInSquareMeters.Should().Be(newFamilyHome.SurfaceInSquareMeters); + familyHomeInDatabase.NumberOfResidents.Should().Be(newFamilyHome.NumberOfResidents); + familyHomeInDatabase.FloorCount.Should().Be(newFamilyHome.FloorCount); + + familyHomeInDatabase.Rooms.Should().HaveCount(3); + familyHomeInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom1.Id); + familyHomeInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom2.Id); + familyHomeInDatabase.Rooms.OfType().Should().ContainSingle(livingRoom => livingRoom.Id == existingLivingRoom.Id); + }); + } + + [Fact] + public async Task Can_update_concrete_derived_resource_at_concrete_base_endpoint() + { + // Arrange + FamilyHome existingFamilyHome = _fakers.FamilyHome.GenerateOne(); + existingFamilyHome.Rooms.Add(_fakers.Kitchen.GenerateOne()); + + FamilyHome newFamilyHome = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.FamilyHomes.Add(existingFamilyHome); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new NoOperationsInheritanceClient(httpClient); + + UpdateBuildingRequestDocument requestBody = new() + { + Data = new DataInUpdateFamilyHomeRequest + { + Id = existingFamilyHome.StringId!, + Attributes = new AttributesInUpdateFamilyHomeRequest + { + SurfaceInSquareMeters = newFamilyHome.SurfaceInSquareMeters!.Value, + NumberOfResidents = newFamilyHome.NumberOfResidents!.Value, + FloorCount = newFamilyHome.FloorCount + } + } + }; + + // Act + PrimaryBuildingResponseDocument? response = + await ApiResponse.TranslateAsync(async () => await apiClient.PatchBuildingAsync(existingFamilyHome.StringId!, requestBody)); + + // Assert + response.Should().NotBeNull(); + + DataInFamilyHomeResponse familyHomeData = response.Data.Should().BeOfType().Subject; + + AttributesInFamilyHomeResponse familyHomeAttributes = familyHomeData.Attributes.Should().BeOfType().Subject; + familyHomeAttributes.SurfaceInSquareMeters.Should().Be(newFamilyHome.SurfaceInSquareMeters); + familyHomeAttributes.NumberOfResidents.Should().Be(newFamilyHome.NumberOfResidents); + familyHomeAttributes.FloorCount.Should().Be(newFamilyHome.FloorCount); + + RelationshipsInFamilyHomeResponse familyHomeRelationships = familyHomeData.Relationships.Should().BeOfType().Subject; + familyHomeRelationships.Rooms.Should().NotBeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + FamilyHome familyHomeInDatabase = await dbContext.FamilyHomes.Include(familyHome => familyHome.Rooms).FirstWithIdAsync(existingFamilyHome.Id); + + familyHomeInDatabase.SurfaceInSquareMeters.Should().Be(newFamilyHome.SurfaceInSquareMeters); + familyHomeInDatabase.NumberOfResidents.Should().Be(newFamilyHome.NumberOfResidents); + familyHomeInDatabase.FloorCount.Should().Be(newFamilyHome.FloorCount); + + familyHomeInDatabase.Rooms.Should().HaveCount(1); + familyHomeInDatabase.Rooms.OfType().Should().ContainSingle(kitchen => kitchen.Id == existingFamilyHome.Rooms.ElementAt(0).Id); + }); + } + + [Fact] + public async Task Can_delete_concrete_derived_resource_at_abstract_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new NoOperationsInheritanceClient(httpClient); + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.DeleteBuildingAsync(existingMansion.StringId!)); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + FamilyHome? familyHomeInDatabase = await dbContext.FamilyHomes.FirstWithIdOrDefaultAsync(existingMansion.Id); + + familyHomeInDatabase.Should().BeNull(); + }); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/ResourceInheritance/OnlyRelationships/RelationshipInheritanceTests.cs b/test/OpenApiNSwagEndToEndTests/ResourceInheritance/OnlyRelationships/RelationshipInheritanceTests.cs new file mode 100644 index 0000000000..9ad2ff8c41 --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/ResourceInheritance/OnlyRelationships/RelationshipInheritanceTests.cs @@ -0,0 +1,896 @@ +using FluentAssertions; +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using OpenApiNSwagEndToEndTests.OnlyRelationshipsInheritance.GeneratedCode; +using OpenApiTests; +using OpenApiTests.ResourceInheritance; +using OpenApiTests.ResourceInheritance.Models; +using OpenApiTests.ResourceInheritance.OnlyRelationships; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.ResourceInheritance.OnlyRelationships; + +public sealed class RelationshipInheritanceTests + : IClassFixture, ResourceInheritanceDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, ResourceInheritanceDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly ResourceInheritanceFakers _fakers = new(); + + public RelationshipInheritanceTests(IntegrationTestContext, ResourceInheritanceDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseInheritanceControllers(true); + + testContext.ConfigureServices(services => + { + services.AddSingleton(); + services.AddSingleton(); + }); + } + + // GET /rooms/1/relationships/residence => familyHome + [Fact] + public async Task Can_get_ToOne_relationship_at_abstract_base_endpoint() + { + // Arrange + Bedroom bedroom = _fakers.Bedroom.GenerateOne(); + bedroom.Residence = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Rooms.Add(bedroom); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new OnlyRelationshipsInheritanceClient(httpClient); + + // Act + ResidenceIdentifierResponseDocument response = await apiClient.GetRoomResidenceRelationshipAsync(bedroom.StringId!); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().BeOfType(); + response.Data.Id.Should().Be(bedroom.Residence.StringId); + } + + // GET /bedrooms/1/relationships/residence => familyHome + [Fact] + public async Task Can_get_ToOne_relationship_at_concrete_derived_endpoint() + { + // Arrange + Bedroom bedroom = _fakers.Bedroom.GenerateOne(); + bedroom.Residence = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Rooms.Add(bedroom); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new OnlyRelationshipsInheritanceClient(httpClient); + + // Act + ResidenceIdentifierResponseDocument response = await apiClient.GetBedroomResidenceRelationshipAsync(bedroom.StringId!); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().BeOfType(); + response.Data.Id.Should().Be(bedroom.Residence.StringId); + } + + // GET /residences/1/relationships/rooms => [kitchen, bedroom] + [Fact] + public async Task Can_get_ToMany_relationship_at_concrete_base_endpoint() + { + // Arrange + Kitchen kitchen = _fakers.Kitchen.GenerateOne(); + Bedroom bedroom = _fakers.Bedroom.GenerateOne(); + + FamilyHome familyHome = _fakers.FamilyHome.GenerateOne(); + familyHome.Rooms.Add(kitchen); + familyHome.Rooms.Add(bedroom); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.FamilyHomes.Add(familyHome); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new OnlyRelationshipsInheritanceClient(httpClient); + + // Act + RoomIdentifierCollectionResponseDocument response = await apiClient.GetResidenceRoomsRelationshipAsync(familyHome.StringId!); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(2); + + response.Data.OfType().Should().ContainSingle(data => data.Id == kitchen.StringId); + response.Data.OfType().Should().ContainSingle(data => data.Id == bedroom.StringId); + } + + // GET /mansions/1/relationships/rooms => [bathroom, toilet] + [Fact] + public async Task Can_get_ToMany_relationship_at_concrete_derived_endpoint() + { + // Arrange + Bathroom bathroom = _fakers.Bathroom.GenerateOne(); + Toilet toilet = _fakers.Toilet.GenerateOne(); + + Mansion mansion = _fakers.Mansion.GenerateOne(); + mansion.Rooms.Add(bathroom); + mansion.Rooms.Add(toilet); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(mansion); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new OnlyRelationshipsInheritanceClient(httpClient); + + // Act + RoomIdentifierCollectionResponseDocument response = await apiClient.GetMansionRoomsRelationshipAsync(mansion.StringId!); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(2); + + response.Data.OfType().Should().ContainSingle(data => data.Id == bathroom.StringId); + response.Data.OfType().Should().ContainSingle(data => data.Id == toilet.StringId); + } + + // PATCH /rooms/1/relationships/residence { type: residence } + [Fact] + public async Task Can_set_concrete_base_resource_at_abstract_ToOne_relationship_endpoint() + { + // Arrange + Bathroom existingBathroom = _fakers.Bathroom.GenerateOne(); + existingBathroom.Residence = _fakers.FamilyHome.GenerateOne(); + + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Bathrooms.Add(existingBathroom); + dbContext.Mansions.Add(existingMansion); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new OnlyRelationshipsInheritanceClient(httpClient); + + var requestBody = new ToOneResidenceInRequest + { + Data = new ResidenceIdentifierInRequest + { + Id = existingMansion.StringId + } + }; + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PatchRoomResidenceRelationshipAsync(existingBathroom.StringId!, requestBody)); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Room roomInDatabase = await dbContext.Rooms.Include(room => room.Residence).FirstWithIdAsync(existingBathroom.Id); + + roomInDatabase.Should().BeOfType(); + + roomInDatabase.Residence.Should().BeOfType(); + roomInDatabase.Residence.Id.Should().Be(existingMansion.Id); + }); + } + + // PATCH /rooms/1/relationships/residence { type: mansion } + [Fact] + public async Task Can_set_concrete_derived_resource_at_abstract_ToOne_relationship_endpoint() + { + // Arrange + Bathroom existingBathroom = _fakers.Bathroom.GenerateOne(); + existingBathroom.Residence = _fakers.FamilyHome.GenerateOne(); + + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Bathrooms.Add(existingBathroom); + dbContext.Mansions.Add(existingMansion); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new OnlyRelationshipsInheritanceClient(httpClient); + + var requestBody = new ToOneResidenceInRequest + { + Data = new MansionIdentifierInRequest + { + Id = existingMansion.StringId + } + }; + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PatchRoomResidenceRelationshipAsync(existingBathroom.StringId!, requestBody)); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Room roomInDatabase = await dbContext.Rooms.Include(room => room.Residence).FirstWithIdAsync(existingBathroom.Id); + + roomInDatabase.Should().BeOfType(); + + roomInDatabase.Residence.Should().BeOfType(); + roomInDatabase.Residence.Id.Should().Be(existingMansion.Id); + }); + } + + // PATCH /bathrooms/1/relationships/residence { type: residence } + [Fact] + public async Task Can_set_concrete_base_resource_at_concrete_derived_ToOne_relationship_endpoint() + { + // Arrange + Bathroom existingBathroom = _fakers.Bathroom.GenerateOne(); + existingBathroom.Residence = _fakers.FamilyHome.GenerateOne(); + + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Bathrooms.Add(existingBathroom); + dbContext.Mansions.Add(existingMansion); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new OnlyRelationshipsInheritanceClient(httpClient); + + var requestBody = new ToOneResidenceInRequest + { + Data = new ResidenceIdentifierInRequest + { + Id = existingMansion.StringId + } + }; + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PatchBathroomResidenceRelationshipAsync(existingBathroom.StringId!, requestBody)); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Room roomInDatabase = await dbContext.Rooms.Include(room => room.Residence).FirstWithIdAsync(existingBathroom.Id); + + roomInDatabase.Should().BeOfType(); + + roomInDatabase.Residence.Should().BeOfType(); + roomInDatabase.Residence.Id.Should().Be(existingMansion.Id); + }); + } + + // PATCH /bathrooms/1/relationships/residence { type: mansion } + [Fact] + public async Task Can_set_concrete_derived_resource_at_concrete_derived_ToOne_relationship_endpoint() + { + // Arrange + Bathroom existingBathroom = _fakers.Bathroom.GenerateOne(); + existingBathroom.Residence = _fakers.FamilyHome.GenerateOne(); + + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Bathrooms.Add(existingBathroom); + dbContext.Mansions.Add(existingMansion); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new OnlyRelationshipsInheritanceClient(httpClient); + + var requestBody = new ToOneResidenceInRequest + { + Data = new MansionIdentifierInRequest + { + Id = existingMansion.StringId + } + }; + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PatchBathroomResidenceRelationshipAsync(existingBathroom.StringId!, requestBody)); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Room roomInDatabase = await dbContext.Rooms.Include(room => room.Residence).FirstWithIdAsync(existingBathroom.Id); + + roomInDatabase.Should().BeOfType(); + + roomInDatabase.Residence.Should().BeOfType(); + roomInDatabase.Residence.Id.Should().Be(existingMansion.Id); + }); + } + + // PATCH /residences/1/relationships/rooms { type: room } + [Fact] + public async Task Can_set_abstract_resources_at_concrete_base_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + existingMansion.Rooms = _fakers.LivingRoom.GenerateSet(1); + + Bedroom existingBedroom = _fakers.Bedroom.GenerateOne(); + existingBedroom.Residence = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + dbContext.Bedrooms.Add(existingBedroom); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new OnlyRelationshipsInheritanceClient(httpClient); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new RoomIdentifierInRequest + { + Id = existingBedroom.StringId + } + ] + }; + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PatchResidenceRoomsRelationshipAsync(existingMansion.StringId!, requestBody)); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().HaveCount(1); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom.Id); + }); + } + + // PATCH /residences/1/relationships/rooms { type: bedroom } + [Fact] + public async Task Can_set_concrete_derived_resources_at_concrete_base_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + existingMansion.Rooms = _fakers.LivingRoom.GenerateSet(1); + + Bedroom existingBedroom = _fakers.Bedroom.GenerateOne(); + existingBedroom.Residence = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + dbContext.Bedrooms.Add(existingBedroom); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new OnlyRelationshipsInheritanceClient(httpClient); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new BedroomIdentifierInRequest + { + Id = existingBedroom.StringId + } + ] + }; + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PatchResidenceRoomsRelationshipAsync(existingMansion.StringId!, requestBody)); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().HaveCount(1); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom.Id); + }); + } + + // PATCH /mansions/1/relationships/rooms { type: room } + [Fact] + public async Task Can_set_abstract_resources_at_concrete_derived_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + existingMansion.Rooms = _fakers.LivingRoom.GenerateSet(1); + + Bedroom existingBedroom = _fakers.Bedroom.GenerateOne(); + existingBedroom.Residence = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + dbContext.Bedrooms.Add(existingBedroom); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new OnlyRelationshipsInheritanceClient(httpClient); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new RoomIdentifierInRequest + { + Id = existingBedroom.StringId + } + ] + }; + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PatchMansionRoomsRelationshipAsync(existingMansion.StringId!, requestBody)); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().HaveCount(1); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom.Id); + }); + } + + // PATCH /mansions/1/relationships/rooms { type: bedroom } + [Fact] + public async Task Can_set_concrete_derived_resources_at_concrete_derived_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + existingMansion.Rooms = _fakers.LivingRoom.GenerateSet(1); + + Bedroom existingBedroom = _fakers.Bedroom.GenerateOne(); + existingBedroom.Residence = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + dbContext.Bedrooms.Add(existingBedroom); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new OnlyRelationshipsInheritanceClient(httpClient); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new BedroomIdentifierInRequest + { + Id = existingBedroom.StringId + } + ] + }; + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PatchMansionRoomsRelationshipAsync(existingMansion.StringId!, requestBody)); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().HaveCount(1); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom.Id); + }); + } + + // POST /residences/1/relationships/rooms { type: room } + [Fact] + public async Task Can_add_abstract_resource_at_concrete_base_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + LivingRoom existingLivingRoom = _fakers.LivingRoom.GenerateOne(); + existingMansion.Rooms.Add(existingLivingRoom); + + Bedroom existingBedroom = _fakers.Bedroom.GenerateOne(); + existingBedroom.Residence = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + dbContext.Bedrooms.Add(existingBedroom); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new OnlyRelationshipsInheritanceClient(httpClient); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new RoomIdentifierInRequest + { + Id = existingBedroom.StringId + } + ] + }; + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PostResidenceRoomsRelationshipAsync(existingMansion.StringId!, requestBody)); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().HaveCount(2); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(livingRoom => livingRoom.Id == existingLivingRoom.Id); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom.Id); + }); + } + + // POST /residences/1/relationships/rooms { type: bedroom } + [Fact] + public async Task Can_add_concrete_derived_resource_at_concrete_base_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + LivingRoom existingLivingRoom = _fakers.LivingRoom.GenerateOne(); + existingMansion.Rooms.Add(existingLivingRoom); + + Bedroom existingBedroom = _fakers.Bedroom.GenerateOne(); + existingBedroom.Residence = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + dbContext.Bedrooms.Add(existingBedroom); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new OnlyRelationshipsInheritanceClient(httpClient); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new BedroomIdentifierInRequest + { + Id = existingBedroom.StringId + } + ] + }; + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PostResidenceRoomsRelationshipAsync(existingMansion.StringId!, requestBody)); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().HaveCount(2); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(livingRoom => livingRoom.Id == existingLivingRoom.Id); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom.Id); + }); + } + + // POST /mansions/1/relationships/rooms { type: room } + [Fact] + public async Task Can_add_abstract_resource_at_concrete_derived_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + LivingRoom existingLivingRoom = _fakers.LivingRoom.GenerateOne(); + existingMansion.Rooms.Add(existingLivingRoom); + + Bedroom existingBedroom = _fakers.Bedroom.GenerateOne(); + existingBedroom.Residence = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + dbContext.Bedrooms.Add(existingBedroom); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new OnlyRelationshipsInheritanceClient(httpClient); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new RoomIdentifierInRequest + { + Id = existingBedroom.StringId + } + ] + }; + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PostMansionRoomsRelationshipAsync(existingMansion.StringId!, requestBody)); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().HaveCount(2); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(livingRoom => livingRoom.Id == existingLivingRoom.Id); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom.Id); + }); + } + + // POST /mansions/1/relationships/rooms { type: bedroom } + [Fact] + public async Task Can_add_concrete_derived_resource_at_concrete_derived_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + LivingRoom existingLivingRoom = _fakers.LivingRoom.GenerateOne(); + existingMansion.Rooms.Add(existingLivingRoom); + + Bedroom existingBedroom = _fakers.Bedroom.GenerateOne(); + existingBedroom.Residence = _fakers.FamilyHome.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + dbContext.Bedrooms.Add(existingBedroom); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new OnlyRelationshipsInheritanceClient(httpClient); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new BedroomIdentifierInRequest + { + Id = existingBedroom.StringId + } + ] + }; + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PostMansionRoomsRelationshipAsync(existingMansion.StringId!, requestBody)); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().HaveCount(2); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(livingRoom => livingRoom.Id == existingLivingRoom.Id); + residenceInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == existingBedroom.Id); + }); + } + + // DELETE /residences/1/relationships/rooms { type: room } + [Fact] + public async Task Can_remove_abstract_resource_at_concrete_base_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + existingMansion.Rooms = _fakers.LivingRoom.GenerateSet(1); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new OnlyRelationshipsInheritanceClient(httpClient); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new RoomIdentifierInRequest + { + Id = existingMansion.Rooms.ElementAt(0).StringId + } + ] + }; + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.DeleteResidenceRoomsRelationshipAsync(existingMansion.StringId!, requestBody)); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().BeEmpty(); + }); + } + + // DELETE /residences/1/relationships/rooms { type: bedroom } + [Fact] + public async Task Can_remove_concrete_derived_resource_at_concrete_base_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + existingMansion.Rooms = _fakers.Bedroom.GenerateSet(1); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new OnlyRelationshipsInheritanceClient(httpClient); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new BedroomIdentifierInRequest + { + Id = existingMansion.Rooms.ElementAt(0).StringId + } + ] + }; + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.DeleteResidenceRoomsRelationshipAsync(existingMansion.StringId!, requestBody)); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().BeEmpty(); + }); + } + + // DELETE /mansions/1/relationships/rooms { type: room } + [Fact] + public async Task Can_remove_abstract_resource_at_concrete_derived_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + existingMansion.Rooms = _fakers.LivingRoom.GenerateSet(1); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new OnlyRelationshipsInheritanceClient(httpClient); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new RoomIdentifierInRequest + { + Id = existingMansion.Rooms.ElementAt(0).StringId + } + ] + }; + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.DeleteMansionRoomsRelationshipAsync(existingMansion.StringId!, requestBody)); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().BeEmpty(); + }); + } + + // DELETE /mansions/1/relationships/rooms { type: bedroom } + [Fact] + public async Task Can_remove_concrete_derived_resource_at_concrete_derived_ToMany_relationship_endpoint() + { + // Arrange + Mansion existingMansion = _fakers.Mansion.GenerateOne(); + existingMansion.Rooms = _fakers.Bedroom.GenerateSet(1); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Mansions.Add(existingMansion); + + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new OnlyRelationshipsInheritanceClient(httpClient); + + var requestBody = new ToManyRoomInRequest + { + Data = + [ + new BedroomIdentifierInRequest + { + Id = existingMansion.Rooms.ElementAt(0).StringId + } + ] + }; + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.DeleteMansionRoomsRelationshipAsync(existingMansion.StringId!, requestBody)); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Residence residenceInDatabase = await dbContext.Residences.Include(residence => residence.Rooms).FirstWithIdAsync(existingMansion.Id); + + residenceInDatabase.Should().BeOfType(); + + residenceInDatabase.Rooms.Should().BeEmpty(); + }); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/ResourceInheritance/SubsetOfOperations/OperationsInheritanceTests.cs b/test/OpenApiNSwagEndToEndTests/ResourceInheritance/SubsetOfOperations/OperationsInheritanceTests.cs new file mode 100644 index 0000000000..617241854b --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/ResourceInheritance/SubsetOfOperations/OperationsInheritanceTests.cs @@ -0,0 +1,326 @@ +using System.Net; +using FluentAssertions; +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using JsonApiDotNetCore.Resources; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using OpenApiNSwagEndToEndTests.SubsetOfOperationsInheritance.GeneratedCode; +using OpenApiTests; +using OpenApiTests.ResourceInheritance; +using OpenApiTests.ResourceInheritance.Models; +using OpenApiTests.ResourceInheritance.SubsetOfOperations; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.ResourceInheritance.SubsetOfOperations; + +public sealed class OperationsInheritanceTests + : IClassFixture, ResourceInheritanceDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, ResourceInheritanceDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly ResourceInheritanceFakers _fakers = new(); + + public OperationsInheritanceTests(IntegrationTestContext, ResourceInheritanceDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseInheritanceControllers(true); + + testContext.ConfigureServices(services => + { + services.AddScoped(typeof(IResourceChangeTracker<>), typeof(NeverSameResourceChangeTracker<>)); + + services.AddSingleton(); + services.AddSingleton(); + }); + } + + [Fact] + public async Task Can_use_inheritance_at_operations_endpoint() + { + // Arrange + StaffMember existingStaffMember = _fakers.StaffMember.GenerateOne(); + + Mansion newMansion = _fakers.Mansion.GenerateOne(); + Kitchen newKitchen = _fakers.Kitchen.GenerateOne(); + FamilyHome newFamilyHome = _fakers.FamilyHome.GenerateOne(); + Bedroom newBedroom = _fakers.Bedroom.GenerateOne(); + int? newFamilyHomeSurfaceInSquareMeters = _fakers.FamilyHome.GenerateOne().SurfaceInSquareMeters; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.StaffMembers.Add(existingStaffMember); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new SubsetOfOperationsInheritanceClient(httpClient); + + const string mansionLid = "mansion-lid"; + const string kitchenLid = "kitchen-lid"; + const string familyHomeLid = "family-home-lid"; + const string bedroomLid = "bedroom-lid"; + + OperationsRequestDocument requestBody = new() + { + Atomic_operations = + [ + // NOTE: CreateBuildingOperation is not generated, because it is turned off. + new CreateResidenceOperation + { + Data = new DataInCreateMansionRequest + { + Lid = mansionLid, + Attributes = new AttributesInCreateMansionRequest + { + SurfaceInSquareMeters = newMansion.SurfaceInSquareMeters!.Value, + NumberOfResidents = newMansion.NumberOfResidents!.Value, + OwnerName = newMansion.OwnerName + }, + Relationships = new RelationshipsInCreateMansionRequest + { + Staff = new ToManyStaffMemberInRequest + { + Data = + [ + new StaffMemberIdentifierInRequest + { + Id = existingStaffMember.StringId + } + ] + } + } + } + }, + // NOTE: It is possible to create an operation for abstract type. + new CreateRoomOperation + { + // NOTE: DataInCreateRoomRequest is generated, but as abstract type. + Data = new DataInCreateKitchenRequest + { + Lid = kitchenLid, + Attributes = new AttributesInCreateKitchenRequest + { + SurfaceInSquareMeters = newKitchen.SurfaceInSquareMeters!.Value, + HasPantry = newKitchen.HasPantry!.Value + }, + Relationships = new RelationshipsInCreateKitchenRequest + { + Residence = new ToOneResidenceInRequest + { + Data = new MansionIdentifierInRequest + { + Lid = mansionLid + } + } + } + } + }, + new CreateFamilyHomeOperation + { + Data = new DataInCreateFamilyHomeRequest + { + Lid = familyHomeLid, + Attributes = new AttributesInCreateFamilyHomeRequest + { + SurfaceInSquareMeters = newFamilyHome.SurfaceInSquareMeters!.Value, + NumberOfResidents = newFamilyHome.NumberOfResidents!.Value, + FloorCount = newFamilyHome.FloorCount + } + } + }, + new CreateBedroomOperation + { + Data = new DataInCreateBedroomRequest + { + Lid = bedroomLid, + Attributes = new AttributesInCreateBedroomRequest + { + SurfaceInSquareMeters = newBedroom.SurfaceInSquareMeters!.Value, + BedCount = newBedroom.BedCount!.Value + }, + Relationships = new RelationshipsInCreateBedroomRequest + { + Residence = new ToOneResidenceInRequest + { + Data = new FamilyHomeIdentifierInRequest + { + Lid = familyHomeLid + } + } + } + } + }, + new AddToFamilyHomeRoomsRelationshipOperation + { + Ref = new FamilyHomeRoomsRelationshipIdentifier + { + Lid = familyHomeLid + }, + Data = + [ + new KitchenIdentifierInRequest + { + Lid = kitchenLid + } + ] + }, + new UpdateResidenceOperation + { + // NOTE: Can use Ref to base type, while Data is derived. + Ref = new ResidenceIdentifierInRequest + { + Lid = familyHomeLid + }, + Data = new DataInUpdateFamilyHomeRequest + { + Lid = familyHomeLid, + Attributes = new AttributesInUpdateFamilyHomeRequest + { + SurfaceInSquareMeters = newFamilyHomeSurfaceInSquareMeters + } + } + }, + new RemoveFromMansionStaffRelationshipOperation + { + Ref = new MansionStaffRelationshipIdentifier + { + Lid = mansionLid + }, + Data = [] + } + ] + }; + + // Act + OperationsResponseDocument? response = await ApiResponse.TranslateAsync(async () => await apiClient.PostOperationsAsync(requestBody)); + + // Assert + response.Should().NotBeNull(); + response.Atomic_results.Should().HaveCount(7); + + DataInMansionResponse mansionData = response.Atomic_results.ElementAt(0).Data.Should().BeOfType().Subject; + AttributesInMansionResponse mansionAttributes = mansionData.Attributes.Should().BeOfType().Subject; + mansionAttributes.SurfaceInSquareMeters.Should().Be(newMansion.SurfaceInSquareMeters); + mansionAttributes.NumberOfResidents.Should().Be(newMansion.NumberOfResidents); + mansionAttributes.OwnerName.Should().Be(newMansion.OwnerName); + mansionData.Relationships.Should().BeNull(); + + DataInKitchenResponse kitchenData = response.Atomic_results.ElementAt(1).Data.Should().BeOfType().Subject; + AttributesInKitchenResponse kitchenAttributes = kitchenData.Attributes.Should().BeOfType().Subject; + kitchenAttributes.SurfaceInSquareMeters.Should().Be(newKitchen.SurfaceInSquareMeters); + kitchenAttributes.HasPantry.Should().Be(newKitchen.HasPantry); + kitchenData.Relationships.Should().BeNull(); + + DataInFamilyHomeResponse familyHomeData2 = response.Atomic_results.ElementAt(2).Data.Should().BeOfType().Subject; + AttributesInFamilyHomeResponse familyHomeAttributes2 = familyHomeData2.Attributes.Should().BeOfType().Subject; + familyHomeAttributes2.SurfaceInSquareMeters.Should().Be(newFamilyHome.SurfaceInSquareMeters); + familyHomeAttributes2.NumberOfResidents.Should().Be(newFamilyHome.NumberOfResidents); + familyHomeAttributes2.FloorCount.Should().Be(newFamilyHome.FloorCount); + familyHomeData2.Relationships.Should().BeNull(); + + DataInBedroomResponse bedroomData = response.Atomic_results.ElementAt(3).Data.Should().BeOfType().Subject; + AttributesInBedroomResponse bedroomAttributes = bedroomData.Attributes.Should().BeOfType().Subject; + bedroomAttributes.SurfaceInSquareMeters.Should().Be(newBedroom.SurfaceInSquareMeters); + bedroomAttributes.BedCount.Should().Be(newBedroom.BedCount); + bedroomData.Relationships.Should().BeNull(); + + response.Atomic_results.ElementAt(4).Data.Should().BeNull(); + + DataInFamilyHomeResponse familyHomeData5 = response.Atomic_results.ElementAt(5).Data.Should().BeOfType().Subject; + AttributesInFamilyHomeResponse familyHomeAttributes5 = familyHomeData5.Attributes.Should().BeOfType().Subject; + familyHomeAttributes5.SurfaceInSquareMeters.Should().Be(newFamilyHomeSurfaceInSquareMeters); + familyHomeAttributes5.NumberOfResidents.Should().Be(newFamilyHome.NumberOfResidents); + familyHomeAttributes5.FloorCount.Should().Be(newFamilyHome.FloorCount); + familyHomeData5.Relationships.Should().BeNull(); + + response.Atomic_results.ElementAt(6).Data.Should().BeNull(); + + long newMansionId = long.Parse(mansionData.Id.Should().NotBeNull().And.Subject); + long newKitchenId = long.Parse(kitchenData.Id.Should().NotBeNull().And.Subject); + long newFamilyHomeId = long.Parse(familyHomeData2.Id.Should().NotBeNull().And.Subject); + long newBedroomId = long.Parse(bedroomData.Id.Should().NotBeNull().And.Subject); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + Mansion mansionInDatabase = + await dbContext.Mansions.Include(mansion => mansion.Rooms).Include(mansion => mansion.Staff).FirstWithIdAsync(newMansionId); + + mansionInDatabase.SurfaceInSquareMeters.Should().Be(newMansion.SurfaceInSquareMeters); + mansionInDatabase.NumberOfResidents.Should().Be(newMansion.NumberOfResidents); + mansionInDatabase.OwnerName.Should().Be(newMansion.OwnerName); + + mansionInDatabase.Rooms.Should().BeEmpty(); + mansionInDatabase.Staff.Should().HaveCount(1); + mansionInDatabase.Staff.ElementAt(0).Id.Should().Be(existingStaffMember.Id); + + FamilyHome familyHomeInDatabase = await dbContext.FamilyHomes.Include(familyHome => familyHome.Rooms).FirstWithIdAsync(newFamilyHomeId); + + familyHomeInDatabase.SurfaceInSquareMeters.Should().Be(newFamilyHomeSurfaceInSquareMeters); + familyHomeInDatabase.NumberOfResidents.Should().Be(newFamilyHome.NumberOfResidents); + familyHomeInDatabase.FloorCount.Should().Be(newFamilyHome.FloorCount); + + familyHomeInDatabase.Rooms.Should().HaveCount(2); + familyHomeInDatabase.Rooms.OfType().Should().ContainSingle(kitchen => kitchen.Id == newKitchenId); + familyHomeInDatabase.Rooms.OfType().Should().ContainSingle(bedroom => bedroom.Id == newBedroomId); + }); + } + + [Fact] + public async Task Cannot_use_base_attributes_type_in_derived_data() + { + // Arrange + int newFamilyHomeSurfaceInSquareMeters = _fakers.FamilyHome.GenerateOne().SurfaceInSquareMeters!.Value; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new SubsetOfOperationsInheritanceClient(httpClient); + + OperationsRequestDocument requestBody = new() + { + Atomic_operations = + [ + new CreateResidenceOperation + { + Data = new DataInCreateFamilyHomeRequest + { + Attributes = new AttributesInCreateResidenceRequest + { + SurfaceInSquareMeters = newFamilyHomeSurfaceInSquareMeters + } + } + } + ] + }; + + // Act + Func action = async () => await ApiResponse.TranslateAsync(async () => await apiClient.PostOperationsAsync(requestBody)); + + // Assert + ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; + exception.StatusCode.Should().Be((int)HttpStatusCode.Conflict); + exception.Result.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Result.Errors.ElementAt(0); + error.Status.Should().Be("409"); + error.Title.Should().Be("Incompatible resource type found."); + error.Detail.Should().Be("Expected openapi:discriminator with value 'familyHomes' instead of 'residences'."); + error.Source.Should().NotBeNull(); + error.Source.Pointer.Should().Be("/atomic:operations[0]/data/attributes/openapi:discriminator"); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/ResourceInheritance/SubsetOfVarious/IncludeTests.cs b/test/OpenApiNSwagEndToEndTests/ResourceInheritance/SubsetOfVarious/IncludeTests.cs new file mode 100644 index 0000000000..5f853fd50a --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/ResourceInheritance/SubsetOfVarious/IncludeTests.cs @@ -0,0 +1,149 @@ +using FluentAssertions; +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Middleware; +using Microsoft.Extensions.DependencyInjection; +using OpenApiNSwagEndToEndTests.SubsetOfVariousInheritance.GeneratedCode; +using OpenApiTests; +using OpenApiTests.ResourceInheritance; +using OpenApiTests.ResourceInheritance.Models; +using OpenApiTests.ResourceInheritance.SubsetOfVarious; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.ResourceInheritance.SubsetOfVarious; + +public sealed class IncludeTests + : IClassFixture, ResourceInheritanceDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, ResourceInheritanceDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly ResourceInheritanceFakers _fakers = new(); + + public IncludeTests(IntegrationTestContext, ResourceInheritanceDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseInheritanceControllers(false); + + testContext.ConfigureServices(services => + { + services.AddSingleton(); + services.AddSingleton(); + }); + } + + [Fact] + public async Task Can_include_in_primary_resources() + { + // Arrange + District district = _fakers.District.GenerateOne(); + + FamilyHome familyHome = _fakers.FamilyHome.GenerateOne(); + familyHome.Rooms.Add(_fakers.LivingRoom.GenerateOne()); + familyHome.Rooms.Add(_fakers.Bedroom.GenerateOne()); + district.Buildings.Add(familyHome); + + Mansion mansion = _fakers.Mansion.GenerateOne(); + mansion.Rooms.Add(_fakers.Kitchen.GenerateOne()); + mansion.Rooms.Add(_fakers.Bathroom.GenerateOne()); + mansion.Rooms.Add(_fakers.Toilet.GenerateOne()); + district.Buildings.Add(mansion); + + Residence residence = _fakers.Residence.GenerateOne(); + residence.Rooms.Add(_fakers.Bedroom.GenerateOne()); + district.Buildings.Add(residence); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.Districts.Add(district); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new SubsetOfVariousInheritanceClient(httpClient); + + var queryString = new Dictionary + { + ["include"] = "buildings.rooms" + }; + + // Act + DistrictCollectionResponseDocument response = await apiClient.GetDistrictCollectionAsync(queryString); + + // Assert + response.Should().NotBeNull(); + response.Data.Should().HaveCount(1); + response.Data.ElementAt(0).Id.Should().Be(district.StringId); + + response.Included.Should().HaveCount(9); + + string familyHomeLivingRoomId = familyHome.Rooms.OfType().Single().StringId!; + string familyRoomBedroomId = familyHome.Rooms.OfType().Single().StringId!; + string mansionKitchenId = mansion.Rooms.OfType().Single().StringId!; + string mansionBathroomId = mansion.Rooms.OfType().Single().StringId!; + string mansionToiletId = mansion.Rooms.OfType().Single().StringId!; + string residenceBedroomId = residence.Rooms.OfType().Single().StringId!; + + response.Included.OfType().Should().ContainSingle(include => include.Id == familyHome.StringId).Subject.With(include => + { + AttributesInFamilyHomeResponse attributes = include.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(familyHome.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(familyHome.NumberOfResidents); + attributes.FloorCount.Should().Be(familyHome.FloorCount); + + RelationshipsInFamilyHomeResponse relationships = include.Relationships.Should().BeOfType().Subject; + + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().HaveCount(2); + relationships.Rooms.Data.OfType().Should().ContainSingle(data => data.Id == familyHomeLivingRoomId); + relationships.Rooms.Data.OfType().Should().ContainSingle(data => data.Id == familyRoomBedroomId); + }); + + response.Included.OfType().Should().ContainSingle(include => include.Id == mansion.StringId).Subject.With(include => + { + AttributesInMansionResponse attributes = include.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(mansion.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(mansion.NumberOfResidents); + attributes.OwnerName.Should().Be(mansion.OwnerName); + + RelationshipsInMansionResponse relationships = include.Relationships.Should().BeOfType().Subject; + + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().HaveCount(3); + relationships.Rooms.Data.OfType().Should().ContainSingle(data => data.Id == mansionKitchenId); + relationships.Rooms.Data.OfType().Should().ContainSingle(data => data.Id == mansionBathroomId); + relationships.Rooms.Data.OfType().Should().ContainSingle(data => data.Id == mansionToiletId); + }); + + response.Included.OfType().Should().ContainSingle(include => include.Id == residence.StringId).Subject.With(include => + { + AttributesInResidenceResponse attributes = include.Attributes.Should().BeOfType().Subject; + + attributes.SurfaceInSquareMeters.Should().Be(residence.SurfaceInSquareMeters); + attributes.NumberOfResidents.Should().Be(residence.NumberOfResidents); + + RelationshipsInResidenceResponse relationships = include.Relationships.Should().BeOfType().Subject; + + relationships.Rooms.Should().NotBeNull(); + relationships.Rooms.Data.Should().HaveCount(1); + relationships.Rooms.Data.OfType().Should().ContainSingle(data => data.Id == residenceBedroomId); + }); + + response.Included.OfType().Should().ContainSingle(include => include.Id == familyHomeLivingRoomId); + response.Included.OfType().Should().ContainSingle(include => include.Id == familyRoomBedroomId); + response.Included.OfType().Should().ContainSingle(include => include.Id == mansionKitchenId); + response.Included.OfType().Should().ContainSingle(include => include.Id == mansionBathroomId); + response.Included.OfType().Should().ContainSingle(include => include.Id == mansionToiletId); + response.Included.OfType().Should().ContainSingle(include => include.Id == residenceBedroomId); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/RestrictedControllers/CreateResourceTests.cs b/test/OpenApiNSwagEndToEndTests/RestrictedControllers/CreateResourceTests.cs new file mode 100644 index 0000000000..0fa4bec354 --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/RestrictedControllers/CreateResourceTests.cs @@ -0,0 +1,214 @@ +using System.Net; +using FluentAssertions; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using Microsoft.EntityFrameworkCore; +using OpenApiNSwagEndToEndTests.RestrictedControllers.GeneratedCode; +using OpenApiTests; +using OpenApiTests.RestrictedControllers; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.RestrictedControllers; + +public sealed class CreateResourceTests : IClassFixture, RestrictionDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, RestrictionDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly RestrictionFakers _fakers = new(); + + public CreateResourceTests(IntegrationTestContext, RestrictionDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseController(); + } + + [Fact] + public async Task Can_create_resource_with_includes_and_fieldsets() + { + // Arrange + DataStream existingVideoStream = _fakers.DataStream.GenerateOne(); + DataStream existingAudioStream = _fakers.DataStream.GenerateOne(); + WriteOnlyChannel newChannel = _fakers.WriteOnlyChannel.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.DataStreams.AddRange(existingVideoStream, existingAudioStream); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + var requestBody = new CreateWriteOnlyChannelRequestDocument + { + Data = new DataInCreateWriteOnlyChannelRequest + { + Attributes = new AttributesInCreateWriteOnlyChannelRequest + { + Name = newChannel.Name, + IsAdultOnly = newChannel.IsAdultOnly + }, + Relationships = new RelationshipsInCreateWriteOnlyChannelRequest + { + VideoStream = new ToOneDataStreamInRequest + { + Data = new DataStreamIdentifierInRequest + { + Id = existingVideoStream.StringId! + } + }, + AudioStreams = new ToManyDataStreamInRequest + { + Data = + [ + new DataStreamIdentifierInRequest + { + Id = existingAudioStream.StringId! + } + ] + } + } + } + }; + + var queryString = new Dictionary + { + ["include"] = "videoStream,audioStreams", + ["fields[writeOnlyChannels]"] = "name,isCommercial,videoStream,audioStreams", + ["fields[dataStreams]"] = "bytesTransmitted" + }; + + // Act + PrimaryWriteOnlyChannelResponseDocument? response = + await ApiResponse.TranslateAsync(async () => await apiClient.PostWriteOnlyChannelAsync(requestBody, queryString)); + + response.Should().NotBeNull(); + + response.Data.Attributes.Should().NotBeNull(); + response.Data.Attributes.Name.Should().Be(newChannel.Name); + response.Data.Attributes.IsCommercial.Should().BeNull(); + response.Data.Attributes.IsAdultOnly.Should().BeNull(); + response.Data.Relationships.Should().NotBeNull(); + response.Data.Relationships.VideoStream.Should().NotBeNull(); + response.Data.Relationships.VideoStream.Data.Should().NotBeNull(); + response.Data.Relationships.VideoStream.Data.Id.Should().Be(existingVideoStream.StringId); + response.Data.Relationships.UltraHighDefinitionVideoStream.Should().BeNull(); + response.Data.Relationships.AudioStreams.Should().NotBeNull(); + response.Data.Relationships.AudioStreams.Data.Should().HaveCount(1); + response.Data.Relationships.AudioStreams.Data.ElementAt(0).Id.Should().Be(existingAudioStream.StringId); + + response.Included.Should().HaveCount(2); + + response.Included.OfType().Should().ContainSingle(include => include.Id == existingVideoStream.StringId).Subject.With( + include => + { + include.Attributes.Should().NotBeNull(); + include.Attributes.BytesTransmitted.Should().Be((long?)existingVideoStream.BytesTransmitted); + }); + + response.Included.OfType().Should().ContainSingle(include => include.Id == existingAudioStream.StringId).Subject.With( + include => + { + include.Attributes.Should().NotBeNull(); + include.Attributes.BytesTransmitted.Should().Be((long?)existingAudioStream.BytesTransmitted); + }); + + long newChannelId = long.Parse(response.Data.Id.Should().NotBeNull().And.Subject); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + // @formatter:wrap_chained_method_calls chop_always + // @formatter:keep_existing_linebreaks true + + WriteOnlyChannel channelInDatabase = await dbContext.WriteOnlyChannels + .Include(channel => channel.VideoStream) + .Include(channel => channel.AudioStreams) + .FirstWithIdAsync(newChannelId); + + // @formatter:keep_existing_linebreaks restore + // @formatter:wrap_chained_method_calls restore + + channelInDatabase.Name.Should().Be(newChannel.Name); + channelInDatabase.IsCommercial.Should().BeNull(); + channelInDatabase.IsAdultOnly.Should().Be(newChannel.IsAdultOnly); + + channelInDatabase.VideoStream.Should().NotBeNull(); + channelInDatabase.VideoStream.Id.Should().Be(existingVideoStream.Id); + + channelInDatabase.AudioStreams.Should().HaveCount(1); + channelInDatabase.AudioStreams.ElementAt(0).Id.Should().Be(existingAudioStream.Id); + }); + } + + [Fact] + public async Task Cannot_create_resource_for_missing_request_body() + { + // Arrange + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + CreateWriteOnlyChannelRequestDocument requestBody = null!; + + // Act + Func action = async () => _ = await apiClient.PostWriteOnlyChannelAsync(requestBody); + + // Assert + await action.Should().ThrowExactlyAsync().WithParameterName("body"); + } + + [Fact] + public async Task Cannot_create_resource_with_unknown_relationship_ID() + { + // Arrange + WriteOnlyChannel newChannel = _fakers.WriteOnlyChannel.GenerateOne(); + + string unknownVideoStreamId = Unknown.StringId.For(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + var requestBody = new CreateWriteOnlyChannelRequestDocument + { + Data = new DataInCreateWriteOnlyChannelRequest + { + Attributes = new AttributesInCreateWriteOnlyChannelRequest + { + Name = newChannel.Name + }, + Relationships = new RelationshipsInCreateWriteOnlyChannelRequest + { + VideoStream = new ToOneDataStreamInRequest + { + Data = new DataStreamIdentifierInRequest + { + Id = unknownVideoStreamId + } + } + } + } + }; + + // Act + Func action = async () => _ = await apiClient.PostWriteOnlyChannelAsync(requestBody); + + // Assert + ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; + exception.StatusCode.Should().Be((int)HttpStatusCode.NotFound); + exception.Message.Should().Be("HTTP 404: A related resource does not exist."); + exception.Result.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Result.Errors.ElementAt(0); + error.Status.Should().Be("404"); + error.Title.Should().Be("A related resource does not exist."); + error.Detail.Should().Be($"Related resource of type 'dataStreams' with ID '{unknownVideoStreamId}' in relationship 'videoStream' does not exist."); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/RestrictedControllers/DeleteResourceTests.cs b/test/OpenApiNSwagEndToEndTests/RestrictedControllers/DeleteResourceTests.cs new file mode 100644 index 0000000000..220f9a009b --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/RestrictedControllers/DeleteResourceTests.cs @@ -0,0 +1,84 @@ +using System.Net; +using FluentAssertions; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using OpenApiNSwagEndToEndTests.RestrictedControllers.GeneratedCode; +using OpenApiTests; +using OpenApiTests.RestrictedControllers; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.RestrictedControllers; + +public sealed class DeleteResourceTests : IClassFixture, RestrictionDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, RestrictionDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly RestrictionFakers _fakers = new(); + + public DeleteResourceTests(IntegrationTestContext, RestrictionDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseController(); + } + + [Fact] + public async Task Can_delete_existing_resource() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + // Act + await apiClient.DeleteWriteOnlyChannelAsync(existingChannel.StringId!); + + // Assert + await _testContext.RunOnDatabaseAsync(async dbContext => + { + WriteOnlyChannel? channelInDatabase = await dbContext.WriteOnlyChannels.FirstWithIdOrDefaultAsync(existingChannel.Id); + + channelInDatabase.Should().BeNull(); + }); + } + + [Fact] + public async Task Cannot_delete_unknown_resource() + { + // Arrange + string unknownChannelId = Unknown.StringId.For(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + // Act + Func action = async () => await apiClient.DeleteWriteOnlyChannelAsync(unknownChannelId); + + // Assert + ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; + exception.StatusCode.Should().Be((int)HttpStatusCode.NotFound); + exception.Message.Should().Be("HTTP 404: The writeOnlyChannel does not exist."); + exception.Result.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Result.Errors.ElementAt(0); + error.Status.Should().Be("404"); + error.Title.Should().Be("The requested resource does not exist."); + error.Detail.Should().Be($"Resource of type 'writeOnlyChannels' with ID '{unknownChannelId}' does not exist."); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/RestrictedControllers/FetchRelationshipTests.cs b/test/OpenApiNSwagEndToEndTests/RestrictedControllers/FetchRelationshipTests.cs new file mode 100644 index 0000000000..e9c3b3198a --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/RestrictedControllers/FetchRelationshipTests.cs @@ -0,0 +1,153 @@ +using System.Net; +using FluentAssertions; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using OpenApiNSwagEndToEndTests.RestrictedControllers.GeneratedCode; +using OpenApiTests; +using OpenApiTests.RestrictedControllers; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.RestrictedControllers; + +public sealed class FetchRelationshipTests : IClassFixture, RestrictionDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, RestrictionDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly RestrictionFakers _fakers = new(); + + public FetchRelationshipTests(IntegrationTestContext, RestrictionDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseController(); + } + + [Fact] + public async Task Can_get_ToOne_relationship() + { + // Arrange + ReadOnlyChannel channel = _fakers.ReadOnlyChannel.GenerateOne(); + channel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.ReadOnlyChannels.Add(channel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + // Act + DataStreamIdentifierResponseDocument response = await apiClient.GetReadOnlyChannelVideoStreamRelationshipAsync(channel.StringId!); + + // Assert + response.Data.Should().NotBeNull(); + response.Data.Id.Should().Be(channel.VideoStream.StringId); + } + + [Fact] + public async Task Can_get_empty_ToOne_relationship() + { + // Arrange + ReadOnlyChannel channel = _fakers.ReadOnlyChannel.GenerateOne(); + channel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.ReadOnlyChannels.Add(channel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + // Act + NullableDataStreamIdentifierResponseDocument response = + await apiClient.GetReadOnlyChannelUltraHighDefinitionVideoStreamRelationshipAsync(channel.StringId!); + + // Assert + response.Data.Should().BeNull(); + } + + [Fact] + public async Task Can_get_ToMany_relationship() + { + // Arrange + ReadOnlyChannel channel = _fakers.ReadOnlyChannel.GenerateOne(); + channel.VideoStream = _fakers.DataStream.GenerateOne(); + channel.AudioStreams = _fakers.DataStream.GenerateSet(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.ReadOnlyChannels.Add(channel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + // Act + DataStreamIdentifierCollectionResponseDocument response = await apiClient.GetReadOnlyChannelAudioStreamsRelationshipAsync(channel.StringId!); + + // Assert + response.Data.Should().HaveCount(2); + response.Data.Should().ContainSingle(autoStream => autoStream.Id == channel.AudioStreams.ElementAt(0).StringId); + response.Data.Should().ContainSingle(autoStream => autoStream.Id == channel.AudioStreams.ElementAt(1).StringId); + } + + [Fact] + public async Task Can_get_empty_ToMany_relationship() + { + // Arrange + ReadOnlyChannel channel = _fakers.ReadOnlyChannel.GenerateOne(); + channel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.ReadOnlyChannels.Add(channel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + // Act + DataStreamIdentifierCollectionResponseDocument response = await apiClient.GetReadOnlyChannelAudioStreamsRelationshipAsync(channel.StringId!); + + // Assert + response.Data.Should().HaveCount(0); + } + + [Fact] + public async Task Cannot_get_relationship_for_unknown_primary_ID() + { + // Arrange + string unknownChannelId = Unknown.StringId.For(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + // Act + Func action = async () => _ = await apiClient.GetReadOnlyChannelVideoStreamRelationshipAsync(unknownChannelId); + + // Assert + ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; + exception.StatusCode.Should().Be((int)HttpStatusCode.NotFound); + exception.Message.Should().Be("HTTP 404: The readOnlyChannel does not exist."); + exception.Result.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Result.Errors.ElementAt(0); + error.Status.Should().Be("404"); + error.Title.Should().Be("The requested resource does not exist."); + error.Detail.Should().Be($"Resource of type 'readOnlyChannels' with ID '{unknownChannelId}' does not exist."); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/RestrictedControllers/FetchResourceTests.cs b/test/OpenApiNSwagEndToEndTests/RestrictedControllers/FetchResourceTests.cs new file mode 100644 index 0000000000..3dfbeaa9cb --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/RestrictedControllers/FetchResourceTests.cs @@ -0,0 +1,269 @@ +using System.Net; +using FluentAssertions; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using OpenApiNSwagEndToEndTests.RestrictedControllers.GeneratedCode; +using OpenApiTests; +using OpenApiTests.RestrictedControllers; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.RestrictedControllers; + +public sealed class FetchResourceTests : IClassFixture, RestrictionDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, RestrictionDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly RestrictionFakers _fakers = new(); + + public FetchResourceTests(IntegrationTestContext, RestrictionDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseController(); + } + + [Fact] + public async Task Can_get_primary_resources() + { + // Arrange + List channels = _fakers.ReadOnlyChannel.GenerateList(2); + channels.ForEach(channel => channel.VideoStream = _fakers.DataStream.GenerateOne()); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + await dbContext.ClearTableAsync(); + dbContext.ReadOnlyChannels.AddRange(channels); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + // Act + ReadOnlyChannelCollectionResponseDocument response = await apiClient.GetReadOnlyChannelCollectionAsync(); + + // Assert + response.Data.Should().HaveCount(2); + + DataInReadOnlyChannelResponse channel1 = response.Data.Single(channel => channel.Id == channels.ElementAt(0).StringId); + channel1.Attributes.Should().NotBeNull(); + channel1.Attributes.Name.Should().Be(channels[0].Name); + channel1.Attributes.IsCommercial.Should().Be(channels[0].IsCommercial); + channel1.Attributes.IsAdultOnly.Should().Be(channels[0].IsAdultOnly); + channel1.Relationships.Should().NotBeNull(); + channel1.Relationships.VideoStream.Should().NotBeNull(); + channel1.Relationships.VideoStream.Data.Should().BeNull(); + channel1.Relationships.UltraHighDefinitionVideoStream.Should().NotBeNull(); + channel1.Relationships.UltraHighDefinitionVideoStream.Data.Should().BeNull(); + channel1.Relationships.AudioStreams.Should().NotBeNull(); + channel1.Relationships.AudioStreams.Data.Should().BeNull(); + + DataInReadOnlyChannelResponse channel2 = response.Data.Single(channel => channel.Id == channels.ElementAt(1).StringId); + channel2.Attributes.Should().NotBeNull(); + channel2.Attributes.Name.Should().Be(channels[1].Name); + channel2.Attributes.IsCommercial.Should().Be(channels[1].IsCommercial); + channel2.Attributes.IsAdultOnly.Should().Be(channels[1].IsAdultOnly); + channel2.Relationships.Should().NotBeNull(); + channel2.Relationships.VideoStream.Should().NotBeNull(); + channel2.Relationships.VideoStream.Data.Should().BeNull(); + channel2.Relationships.UltraHighDefinitionVideoStream.Should().NotBeNull(); + channel2.Relationships.UltraHighDefinitionVideoStream.Data.Should().BeNull(); + channel2.Relationships.AudioStreams.Should().NotBeNull(); + channel2.Relationships.AudioStreams.Data.Should().BeNull(); + } + + [Fact] + public async Task Can_get_primary_resource_by_ID() + { + // Arrange + ReadOnlyChannel channel = _fakers.ReadOnlyChannel.GenerateOne(); + channel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.ReadOnlyChannels.Add(channel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + // Act + PrimaryReadOnlyChannelResponseDocument response = await apiClient.GetReadOnlyChannelAsync(channel.StringId!); + + // Assert + response.Data.Should().NotBeNull(); + response.Data.Id.Should().Be(channel.StringId); + response.Data.Attributes.Should().NotBeNull(); + response.Data.Attributes.Name.Should().Be(channel.Name); + response.Data.Attributes.IsCommercial.Should().Be(channel.IsCommercial); + response.Data.Attributes.IsAdultOnly.Should().Be(channel.IsAdultOnly); + response.Data.Relationships.Should().NotBeNull(); + response.Data.Relationships.VideoStream.Should().NotBeNull(); + response.Data.Relationships.VideoStream.Data.Should().BeNull(); + response.Data.Relationships.UltraHighDefinitionVideoStream.Should().NotBeNull(); + response.Data.Relationships.UltraHighDefinitionVideoStream.Data.Should().BeNull(); + response.Data.Relationships.AudioStreams.Should().NotBeNull(); + response.Data.Relationships.AudioStreams.Data.Should().BeNull(); + } + + [Fact] + public async Task Cannot_get_primary_resource_for_unknown_ID() + { + // Arrange + string unknownChannelId = Unknown.StringId.For(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + // Act + Func action = async () => _ = await apiClient.GetReadOnlyChannelAsync(unknownChannelId); + + // Assert + ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; + exception.StatusCode.Should().Be((int)HttpStatusCode.NotFound); + exception.Message.Should().Be("HTTP 404: The readOnlyChannel does not exist."); + exception.Result.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Result.Errors.ElementAt(0); + error.Status.Should().Be("404"); + error.Title.Should().Be("The requested resource does not exist."); + error.Detail.Should().Be($"Resource of type 'readOnlyChannels' with ID '{unknownChannelId}' does not exist."); + } + + [Fact] + public async Task Can_get_secondary_ToOne_resource() + { + // Arrange + ReadOnlyChannel channel = _fakers.ReadOnlyChannel.GenerateOne(); + channel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.ReadOnlyChannels.Add(channel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + // Act + SecondaryDataStreamResponseDocument response = await apiClient.GetReadOnlyChannelVideoStreamAsync(channel.StringId!); + + // Assert + response.Data.Should().NotBeNull(); + response.Data.Id.Should().Be(channel.VideoStream.StringId); + response.Data.Attributes.Should().NotBeNull(); + response.Data.Attributes.BytesTransmitted.Should().Be((long?)channel.VideoStream.BytesTransmitted); + } + + [Fact] + public async Task Can_get_unknown_secondary_ToOne_resource() + { + // Arrange + ReadOnlyChannel channel = _fakers.ReadOnlyChannel.GenerateOne(); + channel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.ReadOnlyChannels.Add(channel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + // Act + NullableSecondaryDataStreamResponseDocument response = await apiClient.GetReadOnlyChannelUltraHighDefinitionVideoStreamAsync(channel.StringId!); + + // Assert + response.Data.Should().BeNull(); + } + + [Fact] + public async Task Can_get_secondary_ToMany_resources() + { + // Arrange + ReadOnlyChannel channel = _fakers.ReadOnlyChannel.GenerateOne(); + channel.VideoStream = _fakers.DataStream.GenerateOne(); + channel.AudioStreams = _fakers.DataStream.GenerateSet(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.ReadOnlyChannels.Add(channel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + // Act + DataStreamCollectionResponseDocument response = await apiClient.GetReadOnlyChannelAudioStreamsAsync(channel.StringId!); + + // Assert + response.Data.Should().HaveCount(2); + + DataInDataStreamResponse audioStream1 = response.Data.Single(autoStream => autoStream.Id == channel.AudioStreams.ElementAt(0).StringId); + audioStream1.Attributes.Should().NotBeNull(); + audioStream1.Attributes.BytesTransmitted.Should().Be((long?)channel.AudioStreams.ElementAt(0).BytesTransmitted); + + DataInDataStreamResponse audioStream2 = response.Data.Single(autoStream => autoStream.Id == channel.AudioStreams.ElementAt(1).StringId); + audioStream2.Attributes.Should().NotBeNull(); + audioStream2.Attributes.BytesTransmitted.Should().Be((long?)channel.AudioStreams.ElementAt(1).BytesTransmitted); + } + + [Fact] + public async Task Can_get_no_secondary_ToMany_resources() + { + // Arrange + ReadOnlyChannel channel = _fakers.ReadOnlyChannel.GenerateOne(); + channel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.ReadOnlyChannels.Add(channel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + // Act + DataStreamCollectionResponseDocument response = await apiClient.GetReadOnlyChannelAudioStreamsAsync(channel.StringId!); + + // Assert + response.Data.Should().HaveCount(0); + } + + [Fact] + public async Task Cannot_get_secondary_resource_for_unknown_primary_ID() + { + // Arrange + string unknownChannelId = Unknown.StringId.For(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + // Act + Func action = async () => _ = await apiClient.GetReadOnlyChannelVideoStreamAsync(unknownChannelId); + + // Assert + ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; + exception.StatusCode.Should().Be((int)HttpStatusCode.NotFound); + exception.Message.Should().Be("HTTP 404: The readOnlyChannel does not exist."); + exception.Result.Errors.Should().HaveCount(1); + + ErrorObject error = exception.Result.Errors.ElementAt(0); + error.Status.Should().Be("404"); + error.Title.Should().Be("The requested resource does not exist."); + error.Detail.Should().Be($"Resource of type 'readOnlyChannels' with ID '{unknownChannelId}' does not exist."); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/RestrictedControllers/UpdateRelationshipTests.cs b/test/OpenApiNSwagEndToEndTests/RestrictedControllers/UpdateRelationshipTests.cs new file mode 100644 index 0000000000..60d20f3281 --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/RestrictedControllers/UpdateRelationshipTests.cs @@ -0,0 +1,403 @@ +using System.Net; +using FluentAssertions; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using Microsoft.EntityFrameworkCore; +using OpenApiNSwagEndToEndTests.RestrictedControllers.GeneratedCode; +using OpenApiTests; +using OpenApiTests.RestrictedControllers; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.RestrictedControllers; + +public sealed class UpdateRelationshipTests : IClassFixture, RestrictionDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, RestrictionDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly RestrictionFakers _fakers = new(); + + public UpdateRelationshipTests(IntegrationTestContext, RestrictionDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseController(); + } + + [Fact] + public async Task Can_replace_ToOne_relationship() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + existingChannel.UltraHighDefinitionVideoStream = _fakers.DataStream.GenerateOne(); + + DataStream existingVideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + dbContext.DataStreams.Add(existingVideoStream); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + var requestBody = new NullableToOneDataStreamInRequest + { + Data = new DataStreamIdentifierInRequest + { + Id = existingVideoStream.StringId! + } + }; + + // Act + await ApiResponse.TranslateAsync(async () => + await apiClient.PatchWriteOnlyChannelUltraHighDefinitionVideoStreamRelationshipAsync(existingChannel.StringId!, requestBody)); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + // @formatter:wrap_chained_method_calls chop_always + // @formatter:keep_existing_linebreaks true + + WriteOnlyChannel channelInDatabase = await dbContext.WriteOnlyChannels + .Include(channel => channel.UltraHighDefinitionVideoStream) + .FirstWithIdAsync(existingChannel.Id); + + // @formatter:keep_existing_linebreaks restore + // @formatter:wrap_chained_method_calls restore + + channelInDatabase.UltraHighDefinitionVideoStream.Should().NotBeNull(); + channelInDatabase.UltraHighDefinitionVideoStream.Id.Should().Be(existingVideoStream.Id); + }); + } + + [Fact] + public async Task Can_clear_ToOne_relationship() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + existingChannel.UltraHighDefinitionVideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + var requestBody = new NullableToOneDataStreamInRequest + { + Data = null + }; + + // Act + await ApiResponse.TranslateAsync(async () => + await apiClient.PatchWriteOnlyChannelUltraHighDefinitionVideoStreamRelationshipAsync(existingChannel.StringId!, requestBody)); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + // @formatter:wrap_chained_method_calls chop_always + // @formatter:keep_existing_linebreaks true + + WriteOnlyChannel channelInDatabase = await dbContext.WriteOnlyChannels + .Include(channel => channel.UltraHighDefinitionVideoStream) + .FirstWithIdAsync(existingChannel.Id); + + // @formatter:keep_existing_linebreaks restore + // @formatter:wrap_chained_method_calls restore + + channelInDatabase.UltraHighDefinitionVideoStream.Should().BeNull(); + }); + } + + [Fact] + public async Task Can_replace_ToMany_relationship() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + existingChannel.AudioStreams = _fakers.DataStream.GenerateSet(2); + + DataStream existingAudioStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + dbContext.DataStreams.Add(existingAudioStream); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + var requestBody = new ToManyDataStreamInRequest + { + Data = + [ + new DataStreamIdentifierInRequest + { + Id = existingAudioStream.StringId! + } + ] + }; + + // Act + await ApiResponse.TranslateAsync(async () => + await apiClient.PatchWriteOnlyChannelAudioStreamsRelationshipAsync(existingChannel.StringId!, requestBody)); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + // @formatter:wrap_chained_method_calls chop_always + // @formatter:keep_existing_linebreaks true + + WriteOnlyChannel channelInDatabase = await dbContext.WriteOnlyChannels + .Include(channel => channel.AudioStreams) + .FirstWithIdAsync(existingChannel.Id); + + // @formatter:keep_existing_linebreaks restore + // @formatter:wrap_chained_method_calls restore + + channelInDatabase.AudioStreams.Should().HaveCount(1); + channelInDatabase.AudioStreams.ElementAt(0).Id.Should().Be(existingAudioStream.Id); + }); + } + + [Fact] + public async Task Can_clear_ToMany_relationship() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + existingChannel.AudioStreams = _fakers.DataStream.GenerateSet(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + var requestBody = new ToManyDataStreamInRequest + { + Data = [] + }; + + // Act + await ApiResponse.TranslateAsync(async () => + await apiClient.PatchWriteOnlyChannelAudioStreamsRelationshipAsync(existingChannel.StringId!, requestBody)); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + // @formatter:wrap_chained_method_calls chop_always + // @formatter:keep_existing_linebreaks true + + WriteOnlyChannel channelInDatabase = await dbContext.WriteOnlyChannels + .Include(channel => channel.AudioStreams) + .FirstWithIdAsync(existingChannel.Id); + + // @formatter:keep_existing_linebreaks restore + // @formatter:wrap_chained_method_calls restore + + channelInDatabase.AudioStreams.Should().BeEmpty(); + }); + } + + [Fact] + public async Task Can_add_to_ToMany_relationship() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + existingChannel.AudioStreams = _fakers.DataStream.GenerateSet(1); + + DataStream existingAudioStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + dbContext.DataStreams.Add(existingAudioStream); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + var requestBody = new ToManyDataStreamInRequest + { + Data = + [ + new DataStreamIdentifierInRequest + { + Id = existingAudioStream.StringId! + } + ] + }; + + // Act + await ApiResponse.TranslateAsync(async () => await apiClient.PostWriteOnlyChannelAudioStreamsRelationshipAsync(existingChannel.StringId!, requestBody)); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + // @formatter:wrap_chained_method_calls chop_always + // @formatter:keep_existing_linebreaks true + + WriteOnlyChannel channelInDatabase = await dbContext.WriteOnlyChannels + .Include(channel => channel.AudioStreams) + .FirstWithIdAsync(existingChannel.Id); + + // @formatter:keep_existing_linebreaks restore + // @formatter:wrap_chained_method_calls restore + + channelInDatabase.AudioStreams.Should().HaveCount(2); + channelInDatabase.AudioStreams.Should().ContainSingle(stream => stream.Id == existingChannel.AudioStreams.ElementAt(0).Id); + channelInDatabase.AudioStreams.Should().ContainSingle(stream => stream.Id == existingAudioStream.Id); + }); + } + + [Fact] + public async Task Can_remove_from_ToMany_relationship() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + existingChannel.AudioStreams = _fakers.DataStream.GenerateSet(3); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + var requestBody = new ToManyDataStreamInRequest + { + Data = + [ + new DataStreamIdentifierInRequest + { + Id = existingChannel.AudioStreams.ElementAt(0).StringId! + }, + new DataStreamIdentifierInRequest + { + Id = existingChannel.AudioStreams.ElementAt(1).StringId! + } + ] + }; + + // Act + await ApiResponse.TranslateAsync(async () => + await apiClient.DeleteWriteOnlyChannelAudioStreamsRelationshipAsync(existingChannel.StringId!, requestBody)); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + // @formatter:wrap_chained_method_calls chop_always + // @formatter:keep_existing_linebreaks true + + WriteOnlyChannel channelInDatabase = await dbContext.WriteOnlyChannels + .Include(channel => channel.AudioStreams) + .FirstWithIdAsync(existingChannel.Id); + + // @formatter:keep_existing_linebreaks restore + // @formatter:wrap_chained_method_calls restore + + channelInDatabase.AudioStreams.Should().HaveCount(1); + channelInDatabase.AudioStreams.ElementAt(0).Id.Should().Be(existingChannel.AudioStreams.ElementAt(2).Id); + }); + } + + [Fact] + public async Task Cannot_update_relationship_for_missing_request_body() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + NullableToOneDataStreamInRequest requestBody = null!; + + // Act + Func action = async () => + await apiClient.PatchWriteOnlyChannelUltraHighDefinitionVideoStreamRelationshipAsync(existingChannel.StringId!, requestBody); + + // Assert + await action.Should().ThrowExactlyAsync().WithParameterName("body"); + } + + [Fact] + public async Task Cannot_update_relationship_with_unknown_relationship_IDs() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + await dbContext.SaveChangesAsync(); + }); + + string unknownAudioStreamId1 = Unknown.StringId.For(); + string unknownAudioStreamId2 = Unknown.StringId.AltFor(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + var requestBody = new ToManyDataStreamInRequest + { + Data = + [ + new DataStreamIdentifierInRequest + { + Id = unknownAudioStreamId1 + }, + new DataStreamIdentifierInRequest + { + Id = unknownAudioStreamId2 + } + ] + }; + + // Act + Func action = async () => await apiClient.PatchWriteOnlyChannelAudioStreamsRelationshipAsync(existingChannel.StringId!, requestBody); + + // Assert + ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; + exception.StatusCode.Should().Be((int)HttpStatusCode.NotFound); + exception.Message.Should().Be("HTTP 404: The writeOnlyChannel or a related resource does not exist."); + exception.Result.Errors.Should().HaveCount(2); + + ErrorObject error1 = exception.Result.Errors.ElementAt(0); + error1.Status.Should().Be("404"); + error1.Title.Should().Be("A related resource does not exist."); + error1.Detail.Should().Be($"Related resource of type 'dataStreams' with ID '{unknownAudioStreamId1}' in relationship 'audioStreams' does not exist."); + + ErrorObject error2 = exception.Result.Errors.ElementAt(1); + error2.Status.Should().Be("404"); + error2.Title.Should().Be("A related resource does not exist."); + error2.Detail.Should().Be($"Related resource of type 'dataStreams' with ID '{unknownAudioStreamId2}' in relationship 'audioStreams' does not exist."); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiNSwagEndToEndTests/RestrictedControllers/UpdateResourceTests.cs b/test/OpenApiNSwagEndToEndTests/RestrictedControllers/UpdateResourceTests.cs new file mode 100644 index 0000000000..526f581898 --- /dev/null +++ b/test/OpenApiNSwagEndToEndTests/RestrictedControllers/UpdateResourceTests.cs @@ -0,0 +1,311 @@ +using System.Net; +using FluentAssertions; +using JsonApiDotNetCore.OpenApi.Client.NSwag; +using JsonApiDotNetCore.Resources; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using OpenApiNSwagEndToEndTests.RestrictedControllers.GeneratedCode; +using OpenApiTests; +using OpenApiTests.RestrictedControllers; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiNSwagEndToEndTests.RestrictedControllers; + +public sealed class UpdateResourceTests : IClassFixture, RestrictionDbContext>>, IDisposable +{ + private readonly IntegrationTestContext, RestrictionDbContext> _testContext; + private readonly XUnitLogHttpMessageHandler _logHttpMessageHandler; + private readonly RestrictionFakers _fakers = new(); + + public UpdateResourceTests(IntegrationTestContext, RestrictionDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + _logHttpMessageHandler = new XUnitLogHttpMessageHandler(testOutputHelper); + + testContext.UseController(); + + testContext.ConfigureServices(services => services.AddScoped(typeof(IResourceChangeTracker<>), typeof(NeverSameResourceChangeTracker<>))); + } + + [Fact] + public async Task Can_update_resource_with_includes_and_fieldsets() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + existingChannel.UltraHighDefinitionVideoStream = _fakers.DataStream.GenerateOne(); + existingChannel.AudioStreams = _fakers.DataStream.GenerateSet(2); + + DataStream existingVideoStream = _fakers.DataStream.GenerateOne(); + string? newChannelName = _fakers.WriteOnlyChannel.GenerateOne().Name; + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + dbContext.DataStreams.Add(existingVideoStream); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + var requestBody = new UpdateWriteOnlyChannelRequestDocument + { + Data = new DataInUpdateWriteOnlyChannelRequest + { + Id = existingChannel.StringId!, + Attributes = new AttributesInUpdateWriteOnlyChannelRequest + { + Name = newChannelName + }, + Relationships = new RelationshipsInUpdateWriteOnlyChannelRequest + { + VideoStream = new ToOneDataStreamInRequest + { + Data = new DataStreamIdentifierInRequest + { + Id = existingVideoStream.StringId! + } + }, + UltraHighDefinitionVideoStream = new NullableToOneDataStreamInRequest + { + Data = null + }, + AudioStreams = new ToManyDataStreamInRequest + { + Data = [] + } + } + } + }; + + var queryString = new Dictionary + { + ["include"] = "videoStream,audioStreams", + ["fields[writeOnlyChannels]"] = "name,isCommercial,videoStream,audioStreams", + ["fields[dataStreams]"] = "bytesTransmitted" + }; + + // Act + PrimaryWriteOnlyChannelResponseDocument? response = await ApiResponse.TranslateAsync(async () => + await apiClient.PatchWriteOnlyChannelAsync(existingChannel.StringId!, requestBody, queryString)); + + response.Should().NotBeNull(); + + response.Data.Id.Should().Be(existingChannel.StringId); + response.Data.Attributes.Should().NotBeNull(); + response.Data.Attributes.Name.Should().Be(newChannelName); + response.Data.Attributes.IsCommercial.Should().Be(existingChannel.IsCommercial); + response.Data.Attributes.IsAdultOnly.Should().BeNull(); + response.Data.Relationships.Should().NotBeNull(); + response.Data.Relationships.VideoStream.Should().NotBeNull(); + response.Data.Relationships.VideoStream.Data.Should().NotBeNull(); + response.Data.Relationships.VideoStream.Data.Id.Should().Be(existingVideoStream.StringId); + response.Data.Relationships.UltraHighDefinitionVideoStream.Should().BeNull(); + response.Data.Relationships.AudioStreams.Should().NotBeNull(); + response.Data.Relationships.AudioStreams.Data.Should().BeEmpty(); + + response.Included.Should().HaveCount(1); + response.Included.OfType().Should().ContainSingle(include => include.Id == existingVideoStream.StringId); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + // @formatter:wrap_chained_method_calls chop_always + // @formatter:keep_existing_linebreaks true + + WriteOnlyChannel channelInDatabase = await dbContext.WriteOnlyChannels + .Include(channel => channel.VideoStream) + .Include(channel => channel.UltraHighDefinitionVideoStream) + .Include(channel => channel.AudioStreams) + .FirstWithIdAsync(existingChannel.Id); + + // @formatter:keep_existing_linebreaks restore + // @formatter:wrap_chained_method_calls restore + + channelInDatabase.Name.Should().Be(newChannelName); + channelInDatabase.IsCommercial.Should().Be(existingChannel.IsCommercial); + channelInDatabase.IsAdultOnly.Should().Be(existingChannel.IsAdultOnly); + + channelInDatabase.VideoStream.Should().NotBeNull(); + channelInDatabase.VideoStream.Id.Should().Be(existingVideoStream.Id); + + channelInDatabase.UltraHighDefinitionVideoStream.Should().BeNull(); + + channelInDatabase.AudioStreams.Should().BeEmpty(); + }); + } + + [Fact] + public async Task Can_update_resource_without_attributes_or_relationships() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + existingChannel.UltraHighDefinitionVideoStream = _fakers.DataStream.GenerateOne(); + existingChannel.AudioStreams = _fakers.DataStream.GenerateSet(2); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + var requestBody = new UpdateWriteOnlyChannelRequestDocument + { + Data = new DataInUpdateWriteOnlyChannelRequest + { + Id = existingChannel.StringId!, + Attributes = new AttributesInUpdateWriteOnlyChannelRequest(), + Relationships = new RelationshipsInUpdateWriteOnlyChannelRequest() + } + }; + + // Act + PrimaryWriteOnlyChannelResponseDocument? response = + await ApiResponse.TranslateAsync(async () => await apiClient.PatchWriteOnlyChannelAsync(existingChannel.StringId!, requestBody)); + + response.Should().NotBeNull(); + + response.Data.Id.Should().Be(existingChannel.StringId); + response.Data.Attributes.Should().NotBeNull(); + response.Data.Attributes.Name.Should().Be(existingChannel.Name); + response.Data.Attributes.IsCommercial.Should().Be(existingChannel.IsCommercial); + response.Data.Attributes.IsAdultOnly.Should().Be(existingChannel.IsAdultOnly); + response.Data.Relationships.Should().NotBeNull(); + response.Data.Relationships.VideoStream.Should().NotBeNull(); + response.Data.Relationships.VideoStream.Data.Should().BeNull(); + response.Data.Relationships.UltraHighDefinitionVideoStream.Should().NotBeNull(); + response.Data.Relationships.UltraHighDefinitionVideoStream.Data.Should().BeNull(); + response.Data.Relationships.AudioStreams.Should().NotBeNull(); + response.Data.Relationships.AudioStreams.Data.Should().BeNull(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + // @formatter:wrap_chained_method_calls chop_always + // @formatter:keep_existing_linebreaks true + + WriteOnlyChannel channelInDatabase = await dbContext.WriteOnlyChannels + .Include(channel => channel.VideoStream) + .Include(channel => channel.UltraHighDefinitionVideoStream) + .Include(channel => channel.AudioStreams) + .FirstWithIdAsync(existingChannel.Id); + + // @formatter:keep_existing_linebreaks restore + // @formatter:wrap_chained_method_calls restore + + channelInDatabase.Name.Should().Be(existingChannel.Name); + channelInDatabase.IsCommercial.Should().Be(existingChannel.IsCommercial); + channelInDatabase.IsAdultOnly.Should().Be(existingChannel.IsAdultOnly); + + channelInDatabase.VideoStream.Should().NotBeNull(); + channelInDatabase.VideoStream.Id.Should().Be(existingChannel.VideoStream.Id); + + channelInDatabase.UltraHighDefinitionVideoStream.Should().NotBeNull(); + channelInDatabase.UltraHighDefinitionVideoStream.Id.Should().Be(existingChannel.UltraHighDefinitionVideoStream.Id); + + channelInDatabase.AudioStreams.Should().HaveCount(2); + }); + } + + [Fact] + public async Task Cannot_update_resource_for_missing_request_body() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + await dbContext.SaveChangesAsync(); + }); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + UpdateWriteOnlyChannelRequestDocument requestBody = null!; + + // Act + Func action = async () => _ = await apiClient.PatchWriteOnlyChannelAsync(existingChannel.StringId!, requestBody); + + // Assert + await action.Should().ThrowExactlyAsync().WithParameterName("body"); + } + + [Fact] + public async Task Cannot_update_resource_with_unknown_relationship_IDs() + { + // Arrange + WriteOnlyChannel existingChannel = _fakers.WriteOnlyChannel.GenerateOne(); + existingChannel.VideoStream = _fakers.DataStream.GenerateOne(); + + await _testContext.RunOnDatabaseAsync(async dbContext => + { + dbContext.WriteOnlyChannels.Add(existingChannel); + await dbContext.SaveChangesAsync(); + }); + + string unknownDataStreamId = Unknown.StringId.For(); + + using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); + var apiClient = new RestrictedControllersClient(httpClient); + + var requestBody = new UpdateWriteOnlyChannelRequestDocument + { + Data = new DataInUpdateWriteOnlyChannelRequest + { + Id = existingChannel.StringId!, + Relationships = new RelationshipsInUpdateWriteOnlyChannelRequest + { + VideoStream = new ToOneDataStreamInRequest + { + Data = new DataStreamIdentifierInRequest + { + Id = unknownDataStreamId + } + }, + AudioStreams = new ToManyDataStreamInRequest + { + Data = + [ + new DataStreamIdentifierInRequest + { + Id = unknownDataStreamId + } + ] + } + } + } + }; + + // Act + Func action = async () => _ = await apiClient.PatchWriteOnlyChannelAsync(existingChannel.StringId!, requestBody); + + // Assert + ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; + exception.StatusCode.Should().Be((int)HttpStatusCode.NotFound); + exception.Message.Should().Be("HTTP 404: The writeOnlyChannel or a related resource does not exist."); + exception.Result.Errors.Should().HaveCount(2); + + ErrorObject error1 = exception.Result.Errors.ElementAt(0); + error1.Status.Should().Be("404"); + error1.Title.Should().Be("A related resource does not exist."); + error1.Detail.Should().Be($"Related resource of type 'dataStreams' with ID '{unknownDataStreamId}' in relationship 'videoStream' does not exist."); + + ErrorObject error2 = exception.Result.Errors.ElementAt(1); + error2.Status.Should().Be("404"); + error2.Title.Should().Be("A related resource does not exist."); + error2.Detail.Should().Be($"Related resource of type 'dataStreams' with ID '{unknownDataStreamId}' in relationship 'audioStreams' does not exist."); + } + + public void Dispose() + { + _logHttpMessageHandler.Dispose(); + } +} diff --git a/test/OpenApiTests/AtomicOperations/Course.cs b/test/OpenApiTests/AtomicOperations/Course.cs new file mode 100644 index 0000000000..de193c6893 --- /dev/null +++ b/test/OpenApiTests/AtomicOperations/Course.cs @@ -0,0 +1,25 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.AtomicOperations; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.AtomicOperations", GenerateControllerEndpoints = JsonApiEndpoints.All & ~JsonApiEndpoints.DeleteRelationship, + ClientIdGeneration = ClientIdGenerationMode.Required)] +public sealed class Course : Identifiable +{ + [Attr] + public string Subject { get; set; } = null!; + + [Attr] + public string? Description { get; set; } + + [HasMany(Capabilities = HasManyCapabilities.All & ~HasManyCapabilities.AllowSet)] + public ISet TaughtBy { get; set; } = new HashSet(); + + [HasMany] + public ISet Enrollments { get; set; } = new HashSet(); +} diff --git a/test/OpenApiTests/AtomicOperations/Enrollment.cs b/test/OpenApiTests/AtomicOperations/Enrollment.cs new file mode 100644 index 0000000000..c89cf2537c --- /dev/null +++ b/test/OpenApiTests/AtomicOperations/Enrollment.cs @@ -0,0 +1,29 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.AtomicOperations; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.AtomicOperations")] +public sealed class Enrollment(OperationsDbContext dbContext) : Identifiable +{ + private readonly TimeProvider _timeProvider = dbContext.TimeProvider; + + private DateOnly Today => DateOnly.FromDateTime(_timeProvider.GetUtcNow().Date); + + [Attr] + public DateOnly EnrolledAt { get; set; } + + [Attr] + public DateOnly? GraduatedAt { get; set; } + + [Attr] + public bool HasGraduated => GraduatedAt != null && GraduatedAt <= Today; + + [HasOne] + public Student Student { get; set; } = null!; + + [HasOne] + public Course Course { get; set; } = null!; +} diff --git a/test/OpenApiTests/AtomicOperations/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/AtomicOperations/GeneratedSwagger/swagger.g.json new file mode 100644 index 0000000000..cb64a5f34b --- /dev/null +++ b/test/OpenApiTests/AtomicOperations/GeneratedSwagger/swagger.g.json @@ -0,0 +1,3682 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "OpenApiTests", + "version": "1.0" + }, + "servers": [ + { + "url": "http://localhost" + } + ], + "paths": { + "/operations": { + "post": { + "tags": [ + "operations" + ], + "summary": "Performs multiple mutations in a linear and atomic manner.", + "operationId": "postOperations", + "requestBody": { + "description": "An array of mutation operations. For syntax, see the [Atomic Operations documentation](https://jsonapi.org/ext/atomic/).", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/operationsRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "All operations were successfully applied, which resulted in additional changes.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/operationsResponseDocument" + } + } + } + }, + "204": { + "description": "All operations were successfully applied, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "An operation is not accessible or a client-generated ID is used.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "addOperationCode": { + "enum": [ + "add" + ], + "type": "string" + }, + "addToCourseEnrollmentsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/courseEnrollmentsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/enrollmentIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "addToCourseTaughtByRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/courseTaughtByRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/teacherIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "addToStudentEnrollmentsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/studentEnrollmentsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/enrollmentIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "addToTeacherMentorsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherMentorsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/studentIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "addToTeacherTeachesRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherTeachesRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/courseIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "atomicOperation": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "type": "string" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "addCourse": "#/components/schemas/createCourseOperation", + "addEnrollment": "#/components/schemas/createEnrollmentOperation", + "addStudent": "#/components/schemas/createStudentOperation", + "addTeacher": "#/components/schemas/createTeacherOperation", + "addToCourseEnrollments": "#/components/schemas/addToCourseEnrollmentsRelationshipOperation", + "addToCourseTaughtBy": "#/components/schemas/addToCourseTaughtByRelationshipOperation", + "addToStudentEnrollments": "#/components/schemas/addToStudentEnrollmentsRelationshipOperation", + "addToTeacherMentors": "#/components/schemas/addToTeacherMentorsRelationshipOperation", + "addToTeacherTeaches": "#/components/schemas/addToTeacherTeachesRelationshipOperation", + "removeCourse": "#/components/schemas/deleteCourseOperation", + "removeEnrollment": "#/components/schemas/deleteEnrollmentOperation", + "removeFromStudentEnrollments": "#/components/schemas/removeFromStudentEnrollmentsRelationshipOperation", + "removeFromTeacherMentors": "#/components/schemas/removeFromTeacherMentorsRelationshipOperation", + "removeFromTeacherTeaches": "#/components/schemas/removeFromTeacherTeachesRelationshipOperation", + "removeTeacher": "#/components/schemas/deleteTeacherOperation", + "updateCourse": "#/components/schemas/updateCourseOperation", + "updateCourseEnrollments": "#/components/schemas/updateCourseEnrollmentsRelationshipOperation", + "updateEnrollment": "#/components/schemas/updateEnrollmentOperation", + "updateEnrollmentCourse": "#/components/schemas/updateEnrollmentCourseRelationshipOperation", + "updateEnrollmentStudent": "#/components/schemas/updateEnrollmentStudentRelationshipOperation", + "updateStudent": "#/components/schemas/updateStudentOperation", + "updateStudentEnrollments": "#/components/schemas/updateStudentEnrollmentsRelationshipOperation", + "updateStudentMentor": "#/components/schemas/updateStudentMentorRelationshipOperation", + "updateTeacher": "#/components/schemas/updateTeacherOperation", + "updateTeacherMentors": "#/components/schemas/updateTeacherMentorsRelationshipOperation", + "updateTeacherTeaches": "#/components/schemas/updateTeacherTeachesRelationshipOperation" + } + }, + "x-abstract": true + }, + "atomicResult": { + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "attributesInCourseResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "subject": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateCourseRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "subject" + ], + "type": "object", + "properties": { + "subject": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateEnrollmentRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "type": "object", + "properties": { + "enrolledAt": { + "type": "string", + "format": "date" + }, + "graduatedAt": { + "type": "string", + "format": "date", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "courses": "#/components/schemas/attributesInCreateCourseRequest", + "enrollments": "#/components/schemas/attributesInCreateEnrollmentRequest", + "students": "#/components/schemas/attributesInCreateStudentRequest", + "teachers": "#/components/schemas/attributesInCreateTeacherRequest" + } + }, + "x-abstract": true + }, + "attributesInCreateStudentRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "emailAddress": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateTeacherRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "emailAddress": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInEnrollmentResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "enrolledAt": { + "type": "string", + "format": "date" + }, + "graduatedAt": { + "type": "string", + "format": "date", + "nullable": true + }, + "hasGraduated": { + "type": "boolean", + "readOnly": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "courses": "#/components/schemas/attributesInCourseResponse", + "enrollments": "#/components/schemas/attributesInEnrollmentResponse", + "students": "#/components/schemas/attributesInStudentResponse", + "teachers": "#/components/schemas/attributesInTeacherResponse" + } + }, + "x-abstract": true + }, + "attributesInStudentResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "emailAddress": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInTeacherResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "emailAddress": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateCourseRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "subject": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateEnrollmentRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "enrolledAt": { + "type": "string", + "format": "date" + }, + "graduatedAt": { + "type": "string", + "format": "date", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "courses": "#/components/schemas/attributesInUpdateCourseRequest", + "enrollments": "#/components/schemas/attributesInUpdateEnrollmentRequest", + "students": "#/components/schemas/attributesInUpdateStudentRequest", + "teachers": "#/components/schemas/attributesInUpdateTeacherRequest" + } + }, + "x-abstract": true + }, + "attributesInUpdateStudentRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "emailAddress": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateTeacherRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "emailAddress": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "courseEnrollmentsRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/courseResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/courseEnrollmentsRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "courseEnrollmentsRelationshipName": { + "enum": [ + "enrollments" + ], + "type": "string" + }, + "courseIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "courseIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/courseResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "courseResourceType": { + "enum": [ + "courses" + ], + "type": "string" + }, + "courseTaughtByRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/courseResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/courseTaughtByRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "courseTaughtByRelationshipName": { + "enum": [ + "taughtBy" + ], + "type": "string" + }, + "createCourseOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateCourseRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createEnrollmentOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateEnrollmentRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createStudentOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateStudentRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createTeacherOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateTeacherRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCourseResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCourseResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCourseResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateCourseRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateCourseRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateCourseRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateEnrollmentRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateEnrollmentRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateEnrollmentRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateStudentRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateStudentRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateStudentRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateTeacherRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateTeacherRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateTeacherRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInEnrollmentResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInEnrollmentResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInEnrollmentResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInStudentResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInStudentResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInStudentResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInTeacherResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInTeacherResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInTeacherResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateCourseRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateCourseRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateCourseRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateEnrollmentRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateEnrollmentRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateEnrollmentRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateStudentRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateStudentRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateStudentRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateTeacherRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateTeacherRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateTeacherRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "deleteCourseOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/courseIdentifierInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "deleteEnrollmentOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/enrollmentIdentifierInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "deleteTeacherOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherIdentifierInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "enrollmentCourseRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/enrollmentResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/enrollmentCourseRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "enrollmentCourseRelationshipName": { + "enum": [ + "course" + ], + "type": "string" + }, + "enrollmentIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "enrollmentIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/enrollmentResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "enrollmentResourceType": { + "enum": [ + "enrollments" + ], + "type": "string" + }, + "enrollmentStudentRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/enrollmentResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/enrollmentStudentRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "enrollmentStudentRelationshipName": { + "enum": [ + "student" + ], + "type": "string" + }, + "errorLinks": { + "type": "object", + "properties": { + "about": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorObject": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorLinks" + } + ], + "nullable": true + }, + "status": { + "type": "string" + }, + "code": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/errorSource" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorResponseDocument": { + "required": [ + "errors", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorTopLevelLinks" + } + ] + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/errorObject" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorSource": { + "type": "object", + "properties": { + "pointer": { + "type": "string", + "nullable": true + }, + "parameter": { + "type": "string", + "nullable": true + }, + "header": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "identifierInRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "courses": "#/components/schemas/courseIdentifierInRequest", + "enrollments": "#/components/schemas/enrollmentIdentifierInRequest", + "students": "#/components/schemas/studentIdentifierInRequest", + "teachers": "#/components/schemas/teacherIdentifierInRequest" + } + }, + "x-abstract": true + }, + "jsonapi": { + "type": "object", + "properties": { + "version": { + "type": "string" + }, + "ext": { + "type": "array", + "items": { + "type": "string" + } + }, + "profile": { + "type": "array", + "items": { + "type": "string" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "meta": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "nullableToOneTeacherInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherIdentifierInRequest" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableToOneTeacherInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherIdentifierInResponse" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "operationsRequestDocument": { + "required": [ + "atomic:operations" + ], + "type": "object", + "properties": { + "atomic:operations": { + "minItems": 1, + "type": "array", + "items": { + "$ref": "#/components/schemas/atomicOperation" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "operationsResponseDocument": { + "required": [ + "atomic:results", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "atomic:results": { + "minItems": 1, + "type": "array", + "items": { + "$ref": "#/components/schemas/atomicResult" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "relationshipLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + } + }, + "additionalProperties": false + }, + "relationshipsInCourseResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "type": "object", + "properties": { + "taughtBy": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTeacherInResponse" + } + ] + }, + "enrollments": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEnrollmentInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateCourseRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "type": "object", + "properties": { + "taughtBy": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTeacherInRequest" + } + ] + }, + "enrollments": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEnrollmentInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateEnrollmentRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "required": [ + "course", + "student" + ], + "type": "object", + "properties": { + "student": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneStudentInRequest" + } + ] + }, + "course": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneCourseInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "courses": "#/components/schemas/relationshipsInCreateCourseRequest", + "enrollments": "#/components/schemas/relationshipsInCreateEnrollmentRequest", + "students": "#/components/schemas/relationshipsInCreateStudentRequest", + "teachers": "#/components/schemas/relationshipsInCreateTeacherRequest" + } + }, + "x-abstract": true + }, + "relationshipsInCreateStudentRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "type": "object", + "properties": { + "mentor": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneTeacherInRequest" + } + ] + }, + "enrollments": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEnrollmentInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateTeacherRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "type": "object", + "properties": { + "teaches": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyCourseInRequest" + } + ] + }, + "mentors": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStudentInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInEnrollmentResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "type": "object", + "properties": { + "student": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneStudentInResponse" + } + ] + }, + "course": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneCourseInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "courses": "#/components/schemas/relationshipsInCourseResponse", + "enrollments": "#/components/schemas/relationshipsInEnrollmentResponse", + "students": "#/components/schemas/relationshipsInStudentResponse", + "teachers": "#/components/schemas/relationshipsInTeacherResponse" + } + }, + "x-abstract": true + }, + "relationshipsInStudentResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "type": "object", + "properties": { + "mentor": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneTeacherInResponse" + } + ] + }, + "enrollments": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEnrollmentInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInTeacherResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "type": "object", + "properties": { + "teaches": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyCourseInResponse" + } + ] + }, + "mentors": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStudentInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateCourseRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "taughtBy": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTeacherInRequest" + } + ] + }, + "enrollments": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEnrollmentInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateEnrollmentRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "student": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneStudentInRequest" + } + ] + }, + "course": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneCourseInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "courses": "#/components/schemas/relationshipsInUpdateCourseRequest", + "enrollments": "#/components/schemas/relationshipsInUpdateEnrollmentRequest", + "students": "#/components/schemas/relationshipsInUpdateStudentRequest", + "teachers": "#/components/schemas/relationshipsInUpdateTeacherRequest" + } + }, + "x-abstract": true + }, + "relationshipsInUpdateStudentRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "mentor": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneTeacherInRequest" + } + ] + }, + "enrollments": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEnrollmentInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateTeacherRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "teaches": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyCourseInRequest" + } + ] + }, + "mentors": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStudentInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "removeFromStudentEnrollmentsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/studentEnrollmentsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/enrollmentIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "removeFromTeacherMentorsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherMentorsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/studentIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "removeFromTeacherTeachesRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherTeachesRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/courseIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "removeOperationCode": { + "enum": [ + "remove" + ], + "type": "string" + }, + "resourceInCreateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "courses": "#/components/schemas/dataInCreateCourseRequest", + "enrollments": "#/components/schemas/dataInCreateEnrollmentRequest", + "students": "#/components/schemas/dataInCreateStudentRequest", + "teachers": "#/components/schemas/dataInCreateTeacherRequest" + } + }, + "x-abstract": true + }, + "resourceInResponse": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "courses": "#/components/schemas/dataInCourseResponse", + "enrollments": "#/components/schemas/dataInEnrollmentResponse", + "students": "#/components/schemas/dataInStudentResponse", + "teachers": "#/components/schemas/dataInTeacherResponse" + } + }, + "x-abstract": true + }, + "resourceInUpdateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "courses": "#/components/schemas/dataInUpdateCourseRequest", + "enrollments": "#/components/schemas/dataInUpdateEnrollmentRequest", + "students": "#/components/schemas/dataInUpdateStudentRequest", + "teachers": "#/components/schemas/dataInUpdateTeacherRequest" + } + }, + "x-abstract": true + }, + "resourceLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceType": { + "enum": [ + "courses", + "enrollments", + "students", + "teachers" + ], + "type": "string" + }, + "studentEnrollmentsRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/studentResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/studentEnrollmentsRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "studentEnrollmentsRelationshipName": { + "enum": [ + "enrollments" + ], + "type": "string" + }, + "studentIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "studentIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/studentResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "studentMentorRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/studentResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/studentMentorRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "studentMentorRelationshipName": { + "enum": [ + "mentor" + ], + "type": "string" + }, + "studentResourceType": { + "enum": [ + "students" + ], + "type": "string" + }, + "teacherIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "teacherIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "teacherMentorsRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherMentorsRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "teacherMentorsRelationshipName": { + "enum": [ + "mentors" + ], + "type": "string" + }, + "teacherResourceType": { + "enum": [ + "teachers" + ], + "type": "string" + }, + "teacherTeachesRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherTeachesRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "teacherTeachesRelationshipName": { + "enum": [ + "teaches" + ], + "type": "string" + }, + "toManyCourseInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/courseIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyCourseInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/courseIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyEnrollmentInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/enrollmentIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyEnrollmentInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/enrollmentIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyStudentInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/studentIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyStudentInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/studentIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyTeacherInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/teacherIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyTeacherInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/teacherIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneCourseInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/courseIdentifierInRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneCourseInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/courseIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneStudentInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/studentIdentifierInRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneStudentInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/studentIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateCourseEnrollmentsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/courseEnrollmentsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/enrollmentIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateCourseOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/courseIdentifierInRequest" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateCourseRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateEnrollmentCourseRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/enrollmentCourseRelationshipIdentifier" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/courseIdentifierInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateEnrollmentOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/enrollmentIdentifierInRequest" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateEnrollmentRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateEnrollmentStudentRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/enrollmentStudentRelationshipIdentifier" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/studentIdentifierInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateOperationCode": { + "enum": [ + "update" + ], + "type": "string" + }, + "updateStudentEnrollmentsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/studentEnrollmentsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/enrollmentIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateStudentMentorRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/studentMentorRelationshipIdentifier" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherIdentifierInRequest" + } + ], + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateStudentOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/studentIdentifierInRequest" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateStudentRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateTeacherMentorsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherMentorsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/studentIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateTeacherOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherIdentifierInRequest" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateTeacherRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateTeacherTeachesRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherTeachesRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/courseIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/test/OpenApiTests/AtomicOperations/OperationsController.cs b/test/OpenApiTests/AtomicOperations/OperationsController.cs new file mode 100644 index 0000000000..1caad7b4d4 --- /dev/null +++ b/test/OpenApiTests/AtomicOperations/OperationsController.cs @@ -0,0 +1,13 @@ +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.Resources; +using Microsoft.Extensions.Logging; + +namespace OpenApiTests.AtomicOperations; + +public sealed class OperationsController( + IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, IOperationsProcessor processor, IJsonApiRequest request, + ITargetedFields targetedFields, IAtomicOperationFilter operationFilter) + : JsonApiOperationsController(options, resourceGraph, loggerFactory, processor, request, targetedFields, operationFilter); diff --git a/test/OpenApiTests/AtomicOperations/OperationsDbContext.cs b/test/OpenApiTests/AtomicOperations/OperationsDbContext.cs new file mode 100644 index 0000000000..21164ba769 --- /dev/null +++ b/test/OpenApiTests/AtomicOperations/OperationsDbContext.cs @@ -0,0 +1,17 @@ +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; +using TestBuildingBlocks; + +namespace OpenApiTests.AtomicOperations; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public sealed class OperationsDbContext(TimeProvider timeProvider, DbContextOptions options) + : TestableDbContext(options) +{ + internal TimeProvider TimeProvider { get; } = timeProvider; + + public DbSet Courses => Set(); + public DbSet Teachers => Set(); + public DbSet Students => Set(); + public DbSet Enrollments => Set(); +} diff --git a/test/OpenApiTests/AtomicOperations/OperationsFakers.cs b/test/OpenApiTests/AtomicOperations/OperationsFakers.cs new file mode 100644 index 0000000000..c77e045faa --- /dev/null +++ b/test/OpenApiTests/AtomicOperations/OperationsFakers.cs @@ -0,0 +1,50 @@ +using Bogus; +using JetBrains.Annotations; +using Microsoft.Extensions.DependencyInjection; +using TestBuildingBlocks; + +// @formatter:wrap_chained_method_calls chop_if_long +// @formatter:wrap_before_first_method_call true + +namespace OpenApiTests.AtomicOperations; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public sealed class OperationsFakers +{ + private readonly Lazy> _lazyCourseFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(course => course.Subject, faker => faker.Lorem.Word()) + .RuleFor(course => course.Description, faker => faker.Lorem.Sentence())); + + private readonly Lazy> _lazyTeacherFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(teacher => teacher.Name, faker => faker.Person.FullName) + .RuleFor(teacher => teacher.EmailAddress, faker => faker.Person.Email)); + + private readonly Lazy> _lazyStudentFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(student => student.Name, faker => faker.Person.FullName) + .RuleFor(student => student.EmailAddress, faker => faker.Person.Email)); + + private readonly Lazy> _lazyEnrollmentFaker; + + public Faker Course => _lazyCourseFaker.Value; + public Faker Teacher => _lazyTeacherFaker.Value; + public Faker Student => _lazyStudentFaker.Value; + public Faker Enrollment => _lazyEnrollmentFaker.Value; + + public OperationsFakers(IServiceProvider serviceProvider) + { + _lazyEnrollmentFaker = new Lazy>(() => new Faker() + .MakeDeterministic() + .CustomInstantiator(_ => new Enrollment(ResolveDbContext(serviceProvider))) + .RuleFor(enrollment => enrollment.EnrolledAt, faker => faker.Date.PastDateOnly()) + .RuleFor(enrollment => enrollment.GraduatedAt, faker => faker.Date.RecentDateOnly())); + } + + private OperationsDbContext ResolveDbContext(IServiceProvider serviceProvider) + { + using IServiceScope scope = serviceProvider.CreateScope(); + return scope.ServiceProvider.GetRequiredService(); + } +} diff --git a/test/OpenApiTests/AtomicOperations/OperationsTests.cs b/test/OpenApiTests/AtomicOperations/OperationsTests.cs new file mode 100644 index 0000000000..f49c10c8a9 --- /dev/null +++ b/test/OpenApiTests/AtomicOperations/OperationsTests.cs @@ -0,0 +1,2437 @@ +using System.Text.Json; +using JsonApiDotNetCore.Configuration; +using Microsoft.Extensions.DependencyInjection; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.AtomicOperations; + +public sealed class OperationsTests : IClassFixture, OperationsDbContext>> +{ + private readonly OpenApiTestContext, OperationsDbContext> _testContext; + + public OperationsTests(OpenApiTestContext, OperationsDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + + testContext.UseController(); + + testContext.SetTestOutputHelper(testOutputHelper); + testContext.SwaggerDocumentOutputDirectory = $"{GetType().Namespace!.Replace('.', '/')}/GeneratedSwagger"; + + var options = (JsonApiOptions)testContext.Factory.Services.GetRequiredService(); + options.IncludeJsonApiVersion = true; + } + + [Fact] + public async Task Operations_endpoint_is_exposed() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./operations.post").Should().BeJson(""" + { + "tags": [ + "operations" + ], + "summary": "Performs multiple mutations in a linear and atomic manner.", + "operationId": "postOperations", + "requestBody": { + "description": "An array of mutation operations. For syntax, see the [Atomic Operations documentation](https://jsonapi.org/ext/atomic/).", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/operationsRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "All operations were successfully applied, which resulted in additional changes.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/operationsResponseDocument" + } + } + } + }, + "204": { + "description": "All operations were successfully applied, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "An operation is not accessible or a client-generated ID is used.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + """); + } + + [Fact] + public async Task Operations_request_component_schemas_are_exposed() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas").With(schemasElement => + { + schemasElement.Should().ContainPath("operationsRequestDocument").Should().BeJson(""" + { + "required": [ + "atomic:operations" + ], + "type": "object", + "properties": { + "atomic:operations": { + "minItems": 1, + "type": "array", + "items": { + "$ref": "#/components/schemas/atomicOperation" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("atomicOperation").Should().BeJson(""" + { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "type": "string" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "addCourse": "#/components/schemas/createCourseOperation", + "addEnrollment": "#/components/schemas/createEnrollmentOperation", + "addStudent": "#/components/schemas/createStudentOperation", + "addTeacher": "#/components/schemas/createTeacherOperation", + "addToCourseEnrollments": "#/components/schemas/addToCourseEnrollmentsRelationshipOperation", + "addToCourseTaughtBy": "#/components/schemas/addToCourseTaughtByRelationshipOperation", + "addToStudentEnrollments": "#/components/schemas/addToStudentEnrollmentsRelationshipOperation", + "addToTeacherMentors": "#/components/schemas/addToTeacherMentorsRelationshipOperation", + "addToTeacherTeaches": "#/components/schemas/addToTeacherTeachesRelationshipOperation", + "removeCourse": "#/components/schemas/deleteCourseOperation", + "removeEnrollment": "#/components/schemas/deleteEnrollmentOperation", + "removeFromStudentEnrollments": "#/components/schemas/removeFromStudentEnrollmentsRelationshipOperation", + "removeFromTeacherMentors": "#/components/schemas/removeFromTeacherMentorsRelationshipOperation", + "removeFromTeacherTeaches": "#/components/schemas/removeFromTeacherTeachesRelationshipOperation", + "removeTeacher": "#/components/schemas/deleteTeacherOperation", + "updateCourse": "#/components/schemas/updateCourseOperation", + "updateCourseEnrollments": "#/components/schemas/updateCourseEnrollmentsRelationshipOperation", + "updateEnrollment": "#/components/schemas/updateEnrollmentOperation", + "updateEnrollmentCourse": "#/components/schemas/updateEnrollmentCourseRelationshipOperation", + "updateEnrollmentStudent": "#/components/schemas/updateEnrollmentStudentRelationshipOperation", + "updateStudent": "#/components/schemas/updateStudentOperation", + "updateStudentEnrollments": "#/components/schemas/updateStudentEnrollmentsRelationshipOperation", + "updateStudentMentor": "#/components/schemas/updateStudentMentorRelationshipOperation", + "updateTeacher": "#/components/schemas/updateTeacherOperation", + "updateTeacherMentors": "#/components/schemas/updateTeacherMentorsRelationshipOperation", + "updateTeacherTeaches": "#/components/schemas/updateTeacherTeachesRelationshipOperation" + } + }, + "x-abstract": true + } + """); + + schemasElement.Should().ContainPath("addOperationCode").Should().BeJson(""" + { + "enum": [ + "add" + ], + "type": "string" + } + """); + + schemasElement.Should().ContainPath("updateOperationCode").Should().BeJson(""" + { + "enum": [ + "update" + ], + "type": "string" + } + """); + + schemasElement.Should().ContainPath("removeOperationCode").Should().BeJson(""" + { + "enum": [ + "remove" + ], + "type": "string" + } + """); + + schemasElement.Should().ContainPath("resourceInCreateRequest").Should().BeJson(""" + { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "courses": "#/components/schemas/dataInCreateCourseRequest", + "enrollments": "#/components/schemas/dataInCreateEnrollmentRequest", + "students": "#/components/schemas/dataInCreateStudentRequest", + "teachers": "#/components/schemas/dataInCreateTeacherRequest" + } + }, + "x-abstract": true + } + """); + + schemasElement.Should().ContainPath("resourceInUpdateRequest").Should().BeJson(""" + { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "courses": "#/components/schemas/dataInUpdateCourseRequest", + "enrollments": "#/components/schemas/dataInUpdateEnrollmentRequest", + "students": "#/components/schemas/dataInUpdateStudentRequest", + "teachers": "#/components/schemas/dataInUpdateTeacherRequest" + } + }, + "x-abstract": true + } + """); + + schemasElement.Should().ContainPath("identifierInRequest").Should().BeJson(""" + { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "courses": "#/components/schemas/courseIdentifierInRequest", + "enrollments": "#/components/schemas/enrollmentIdentifierInRequest", + "students": "#/components/schemas/studentIdentifierInRequest", + "teachers": "#/components/schemas/teacherIdentifierInRequest" + } + }, + "x-abstract": true + } + """); + + schemasElement.Should().ContainPath("resourceType").Should().BeJson(""" + { + "enum": [ + "courses", + "enrollments", + "students", + "teachers" + ], + "type": "string" + } + """); + }); + } + + [Fact] + public async Task Operations_response_component_schemas_are_exposed() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas").With(schemasElement => + { + schemasElement.Should().ContainPath("operationsResponseDocument").Should().BeJson(""" + { + "required": [ + "atomic:results", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "atomic:results": { + "minItems": 1, + "type": "array", + "items": { + "$ref": "#/components/schemas/atomicResult" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("atomicResult").Should().BeJson(""" + { + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + } + """); + }); + } + + [Fact] + public async Task Course_operation_component_schemas_are_exposed() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas").With(schemasElement => + { + // resource operations + schemasElement.Should().ContainPath("createCourseOperation").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateCourseRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("dataInCreateCourseRequest").Should().BeJson(""" + { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateCourseRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateCourseRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("attributesInCreateCourseRequest").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "subject" + ], + "type": "object", + "properties": { + "subject": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("relationshipsInCreateCourseRequest").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "type": "object", + "properties": { + "taughtBy": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTeacherInRequest" + } + ] + }, + "enrollments": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEnrollmentInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("updateCourseOperation").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/courseIdentifierInRequest" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateCourseRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("dataInUpdateCourseRequest").Should().BeJson(""" + { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateCourseRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateCourseRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("attributesInUpdateCourseRequest").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "subject": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("relationshipsInUpdateCourseRequest").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "taughtBy": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyTeacherInRequest" + } + ] + }, + "enrollments": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEnrollmentInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("deleteCourseOperation").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/courseIdentifierInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + // relationship operations + schemasElement.Should().ContainPath("updateCourseEnrollmentsRelationshipOperation").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/courseEnrollmentsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/enrollmentIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("addToCourseEnrollmentsRelationshipOperation").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/courseEnrollmentsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/enrollmentIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().NotContainPath("removeFromCourseEnrollmentsRelationshipOperation"); + + schemasElement.Should().NotContainPath("updateCourseTaughtByRelationshipOperation"); + + // shared types + schemasElement.Should().ContainPath("courseIdentifierInRequest").Should().BeJson(""" + { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("courseEnrollmentsRelationshipIdentifier").Should().BeJson(""" + { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/courseResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/courseEnrollmentsRelationshipName" + } + ] + } + }, + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("courseEnrollmentsRelationshipName").Should().BeJson(""" + { + "enum": [ + "enrollments" + ], + "type": "string" + } + """); + }); + } + + [Fact] + public async Task Student_operation_component_schemas_are_exposed() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas").With(schemasElement => + { + // resource operations + schemasElement.Should().ContainPath("createStudentOperation").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateStudentRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("dataInCreateStudentRequest").Should().BeJson(""" + { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateStudentRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateStudentRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("attributesInCreateStudentRequest").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "emailAddress": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("relationshipsInCreateStudentRequest").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "type": "object", + "properties": { + "mentor": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneTeacherInRequest" + } + ] + }, + "enrollments": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEnrollmentInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("updateStudentOperation").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/studentIdentifierInRequest" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateStudentRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("dataInUpdateStudentRequest").Should().BeJson(""" + { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateStudentRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateStudentRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("attributesInUpdateStudentRequest").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "emailAddress": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("relationshipsInUpdateStudentRequest").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "mentor": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneTeacherInRequest" + } + ] + }, + "enrollments": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEnrollmentInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().NotContainPath("deleteStudentOperation"); + + // relationship operations + schemasElement.Should().ContainPath("updateStudentMentorRelationshipOperation").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/studentMentorRelationshipIdentifier" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherIdentifierInRequest" + } + ], + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("updateStudentEnrollmentsRelationshipOperation").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/studentEnrollmentsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/enrollmentIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("addToStudentEnrollmentsRelationshipOperation").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/studentEnrollmentsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/enrollmentIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("removeFromStudentEnrollmentsRelationshipOperation").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/studentEnrollmentsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/enrollmentIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + // shared types + schemasElement.Should().ContainPath("studentIdentifierInRequest").Should().BeJson(""" + { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("studentMentorRelationshipIdentifier").Should().BeJson(""" + { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/studentResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/studentMentorRelationshipName" + } + ] + } + }, + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("studentMentorRelationshipName").Should().BeJson(""" + { + "enum": [ + "mentor" + ], + "type": "string" + } + """); + + schemasElement.Should().ContainPath("studentEnrollmentsRelationshipIdentifier").Should().BeJson(""" + { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/studentResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/studentEnrollmentsRelationshipName" + } + ] + } + }, + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("studentEnrollmentsRelationshipName").Should().BeJson(""" + { + "enum": [ + "enrollments" + ], + "type": "string" + } + """); + }); + } + + [Fact] + public async Task Teacher_operation_component_schemas_are_exposed() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas").With(schemasElement => + { + // resource operations + schemasElement.Should().ContainPath("createTeacherOperation").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateTeacherRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("dataInCreateTeacherRequest").Should().BeJson(""" + { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateTeacherRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateTeacherRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("attributesInCreateTeacherRequest").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "emailAddress": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("relationshipsInCreateTeacherRequest").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "type": "object", + "properties": { + "teaches": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyCourseInRequest" + } + ] + }, + "mentors": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStudentInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("updateTeacherOperation").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherIdentifierInRequest" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateTeacherRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("dataInUpdateTeacherRequest").Should().BeJson(""" + { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateTeacherRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateTeacherRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("attributesInUpdateTeacherRequest").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "emailAddress": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("relationshipsInUpdateTeacherRequest").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "teaches": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyCourseInRequest" + } + ] + }, + "mentors": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStudentInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("deleteTeacherOperation").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherIdentifierInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + // relationship operations + schemasElement.Should().ContainPath("updateTeacherMentorsRelationshipOperation").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherMentorsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/studentIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("addToTeacherMentorsRelationshipOperation").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherMentorsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/studentIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("removeFromTeacherMentorsRelationshipOperation").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherMentorsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/studentIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + // shared types + schemasElement.Should().ContainPath("teacherIdentifierInRequest").Should().BeJson(""" + { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("teacherMentorsRelationshipIdentifier").Should().BeJson(""" + { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/teacherMentorsRelationshipName" + } + ] + } + }, + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("teacherMentorsRelationshipName").Should().BeJson(""" + { + "enum": [ + "mentors" + ], + "type": "string" + } + """); + }); + } + + [Fact] + public async Task Enrollment_operation_component_schemas_are_exposed() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas").With(schemasElement => + { + // resource operations + schemasElement.Should().ContainPath("createEnrollmentOperation").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateEnrollmentRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("dataInCreateEnrollmentRequest").Should().BeJson(""" + { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateEnrollmentRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateEnrollmentRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("attributesInCreateEnrollmentRequest").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "type": "object", + "properties": { + "enrolledAt": { + "type": "string", + "format": "date" + }, + "graduatedAt": { + "type": "string", + "format": "date", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("relationshipsInCreateEnrollmentRequest").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "required": [ + "course", + "student" + ], + "type": "object", + "properties": { + "student": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneStudentInRequest" + } + ] + }, + "course": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneCourseInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("updateEnrollmentOperation").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/enrollmentIdentifierInRequest" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateEnrollmentRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("dataInUpdateEnrollmentRequest").Should().BeJson(""" + { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateEnrollmentRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateEnrollmentRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("attributesInUpdateEnrollmentRequest").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "enrolledAt": { + "type": "string", + "format": "date" + }, + "graduatedAt": { + "type": "string", + "format": "date", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("relationshipsInUpdateEnrollmentRequest").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "student": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneStudentInRequest" + } + ] + }, + "course": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneCourseInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("deleteEnrollmentOperation").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/enrollmentIdentifierInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + // relationship operations + schemasElement.Should().ContainPath("updateEnrollmentCourseRelationshipOperation").Should().BeJson(""" + { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/enrollmentCourseRelationshipIdentifier" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/courseIdentifierInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + // shared types + schemasElement.Should().ContainPath("enrollmentIdentifierInRequest").Should().BeJson(""" + { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("enrollmentCourseRelationshipIdentifier").Should().BeJson(""" + { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/enrollmentResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/enrollmentCourseRelationshipName" + } + ] + } + }, + "additionalProperties": false + } + """); + + schemasElement.Should().ContainPath("enrollmentCourseRelationshipName").Should().BeJson(""" + { + "enum": [ + "course" + ], + "type": "string" + } + """); + }); + } +} diff --git a/test/OpenApiTests/AtomicOperations/Student.cs b/test/OpenApiTests/AtomicOperations/Student.cs new file mode 100644 index 0000000000..465fa52bc0 --- /dev/null +++ b/test/OpenApiTests/AtomicOperations/Student.cs @@ -0,0 +1,23 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.AtomicOperations; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.AtomicOperations", GenerateControllerEndpoints = JsonApiEndpoints.All & ~JsonApiEndpoints.Delete)] +public sealed class Student : Identifiable +{ + [Attr] + public string Name { get; set; } = null!; + + [Attr] + public string? EmailAddress { get; set; } + + [HasOne] + public Teacher? Mentor { get; set; } + + [HasMany] + public ISet Enrollments { get; set; } = new HashSet(); +} diff --git a/test/OpenApiTests/AtomicOperations/Teacher.cs b/test/OpenApiTests/AtomicOperations/Teacher.cs new file mode 100644 index 0000000000..86ff5bb4d4 --- /dev/null +++ b/test/OpenApiTests/AtomicOperations/Teacher.cs @@ -0,0 +1,22 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.AtomicOperations; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.AtomicOperations")] +public sealed class Teacher : Identifiable +{ + [Attr] + public string Name { get; set; } = null!; + + [Attr] + public string? EmailAddress { get; set; } + + [HasMany] + public ISet Teaches { get; set; } = new HashSet(); + + [HasMany] + public ISet Mentors { get; set; } = new HashSet(); +} diff --git a/test/OpenApiTests/ClientIdGenerationModes/ClientIdGenerationDbContext.cs b/test/OpenApiTests/ClientIdGenerationModes/ClientIdGenerationDbContext.cs new file mode 100644 index 0000000000..feb897baaa --- /dev/null +++ b/test/OpenApiTests/ClientIdGenerationModes/ClientIdGenerationDbContext.cs @@ -0,0 +1,14 @@ +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; +using TestBuildingBlocks; + +namespace OpenApiTests.ClientIdGenerationModes; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public sealed class ClientIdGenerationDbContext(DbContextOptions options) + : TestableDbContext(options) +{ + public DbSet Players => Set(); + public DbSet Games => Set(); + public DbSet PlayerGroups => Set(); +} diff --git a/test/OpenApiTests/ClientIdGenerationModes/ClientIdGenerationFakers.cs b/test/OpenApiTests/ClientIdGenerationModes/ClientIdGenerationFakers.cs new file mode 100644 index 0000000000..d97da54070 --- /dev/null +++ b/test/OpenApiTests/ClientIdGenerationModes/ClientIdGenerationFakers.cs @@ -0,0 +1,29 @@ +using Bogus; +using JetBrains.Annotations; +using TestBuildingBlocks; + +// @formatter:wrap_chained_method_calls chop_if_long +// @formatter:wrap_before_first_method_call true + +namespace OpenApiTests.ClientIdGenerationModes; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public sealed class ClientIdGenerationFakers +{ + private readonly Lazy> _lazyPlayerFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(player => player.UserName, faker => faker.Person.UserName)); + + private readonly Lazy> _lazyGameFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(game => game.Title, faker => faker.Commerce.ProductName()) + .RuleFor(game => game.PurchasePrice, faker => faker.Finance.Amount(1, 80))); + + private readonly Lazy> _lazyGroupFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(playerGroup => playerGroup.Name, faker => faker.Person.Company.Name)); + + public Faker Player => _lazyPlayerFaker.Value; + public Faker Game => _lazyGameFaker.Value; + public Faker Group => _lazyGroupFaker.Value; +} diff --git a/test/OpenApiTests/ClientIdGenerationModes/ClientIdGenerationTests.cs b/test/OpenApiTests/ClientIdGenerationModes/ClientIdGenerationTests.cs new file mode 100644 index 0000000000..91f6e20ee4 --- /dev/null +++ b/test/OpenApiTests/ClientIdGenerationModes/ClientIdGenerationTests.cs @@ -0,0 +1,69 @@ +using System.Text.Json; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.ClientIdGenerationModes; + +public sealed class ClientIdGenerationTests : IClassFixture, ClientIdGenerationDbContext>> +{ + private readonly OpenApiTestContext, ClientIdGenerationDbContext> _testContext; + + public ClientIdGenerationTests(OpenApiTestContext, ClientIdGenerationDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + + testContext.SetTestOutputHelper(testOutputHelper); + testContext.SwaggerDocumentOutputDirectory = $"{GetType().Namespace!.Replace('.', '/')}/GeneratedSwagger"; + } + + [Fact] + public async Task Schema_property_for_ID_is_required_in_post_request() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.dataInCreatePlayerRequest.allOf[1]").With(dataElement => + { + dataElement.Should().ContainPath("required").With(requiredElement => + { + requiredElement.Should().ContainArrayElement("id"); + requiredElement.Should().NotContainArrayElement("lid"); + }); + + dataElement.Should().ContainPath("properties.id"); + }); + } + + [Fact] + public async Task Schema_property_for_ID_is_optional_in_post_request() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.dataInCreateGameRequest.allOf[1]").With(dataElement => + { + dataElement.Should().NotContainPath("required"); + }); + } + + [Fact] + public async Task Schema_property_for_ID_is_omitted_in_post_request() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.dataInCreatePlayerGroupRequest.allOf[1]").With(dataElement => + { + dataElement.Should().NotContainPath("required"); + }); + } +} diff --git a/test/OpenApiTests/ClientIdGenerationModes/Game.cs b/test/OpenApiTests/ClientIdGenerationModes/Game.cs new file mode 100644 index 0000000000..c4880054c1 --- /dev/null +++ b/test/OpenApiTests/ClientIdGenerationModes/Game.cs @@ -0,0 +1,19 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.ClientIdGenerationModes; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.ClientIdGenerationModes", ClientIdGeneration = ClientIdGenerationMode.Allowed, + GenerateControllerEndpoints = JsonApiEndpoints.Post)] +public sealed class Game : Identifiable +{ + [Attr] + public string Title { get; set; } = null!; + + [Attr] + public decimal PurchasePrice { get; set; } +} diff --git a/test/OpenApiTests/ClientIdGenerationModes/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/ClientIdGenerationModes/GeneratedSwagger/swagger.g.json new file mode 100644 index 0000000000..0a32442e86 --- /dev/null +++ b/test/OpenApiTests/ClientIdGenerationModes/GeneratedSwagger/swagger.g.json @@ -0,0 +1,1633 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "OpenApiTests", + "version": "1.0" + }, + "servers": [ + { + "url": "http://localhost" + } + ], + "paths": { + "/games": { + "post": { + "tags": [ + "games" + ], + "summary": "Creates a new game.", + "operationId": "postGame", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the game to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createGameRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The game was successfully created, which resulted in additional changes. The newly created game is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created game can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryGameResponseDocument" + } + } + } + }, + "204": { + "description": "The game was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/playerGroups": { + "post": { + "tags": [ + "playerGroups" + ], + "summary": "Creates a new playerGroup.", + "operationId": "postPlayerGroup", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the playerGroup to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createPlayerGroupRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The playerGroup was successfully created, which resulted in additional changes. The newly created playerGroup is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created playerGroup can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryPlayerGroupResponseDocument" + } + } + } + }, + "204": { + "description": "The playerGroup was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/players": { + "post": { + "tags": [ + "players" + ], + "summary": "Creates a new player.", + "operationId": "postPlayer", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the player to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createPlayerRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The player was successfully created, which resulted in additional changes. The newly created player is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created player can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryPlayerResponseDocument" + } + } + } + }, + "204": { + "description": "The player was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "attributesInCreateGameRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "title" + ], + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "purchasePrice": { + "type": "number", + "format": "double" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreatePlayerGroupRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreatePlayerRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "userName" + ], + "type": "object", + "properties": { + "userName": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "games": "#/components/schemas/attributesInCreateGameRequest", + "playerGroups": "#/components/schemas/attributesInCreatePlayerGroupRequest", + "players": "#/components/schemas/attributesInCreatePlayerRequest" + } + }, + "x-abstract": true + }, + "attributesInGameResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "purchasePrice": { + "type": "number", + "format": "double" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInPlayerGroupResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInPlayerResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "userName": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "games": "#/components/schemas/attributesInGameResponse", + "playerGroups": "#/components/schemas/attributesInPlayerGroupResponse", + "players": "#/components/schemas/attributesInPlayerResponse" + } + }, + "x-abstract": true + }, + "createGameRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateGameRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "createPlayerGroupRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreatePlayerGroupRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "createPlayerRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreatePlayerRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "dataInCreateGameRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateGameRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreatePlayerGroupRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreatePlayerGroupRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreatePlayerGroupRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreatePlayerRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreatePlayerRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreatePlayerRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInGameResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInGameResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInPlayerGroupResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInPlayerGroupResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInPlayerGroupResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInPlayerResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInPlayerResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInPlayerResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "errorLinks": { + "type": "object", + "properties": { + "about": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorObject": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorLinks" + } + ], + "nullable": true + }, + "status": { + "type": "string" + }, + "code": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/errorSource" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorResponseDocument": { + "required": [ + "errors", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorTopLevelLinks" + } + ] + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/errorObject" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorSource": { + "type": "object", + "properties": { + "pointer": { + "type": "string", + "nullable": true + }, + "parameter": { + "type": "string", + "nullable": true + }, + "header": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "gameIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "gameIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/gameResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "gameResourceType": { + "enum": [ + "games" + ], + "type": "string" + }, + "identifierInRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "games": "#/components/schemas/gameIdentifierInRequest", + "playerGroups": "#/components/schemas/playerGroupIdentifierInRequest", + "players": "#/components/schemas/playerIdentifierInRequest" + } + }, + "x-abstract": true + }, + "meta": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "playerGroupIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "playerGroupIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/playerGroupResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "playerGroupResourceType": { + "enum": [ + "playerGroups" + ], + "type": "string" + }, + "playerIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "playerIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/playerResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "playerResourceType": { + "enum": [ + "players" + ], + "type": "string" + }, + "primaryGameResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInGameResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryPlayerGroupResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInPlayerGroupResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryPlayerResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInPlayerResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "relationshipLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + } + }, + "additionalProperties": false + }, + "relationshipsInCreatePlayerGroupRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "type": "object", + "properties": { + "players": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyPlayerInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreatePlayerRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "type": "object", + "properties": { + "ownedGames": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyGameInRequest" + } + ] + }, + "memberOf": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyPlayerGroupInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "playerGroups": "#/components/schemas/relationshipsInCreatePlayerGroupRequest", + "players": "#/components/schemas/relationshipsInCreatePlayerRequest" + } + }, + "x-abstract": true + }, + "relationshipsInPlayerGroupResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "type": "object", + "properties": { + "players": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyPlayerInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInPlayerResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "type": "object", + "properties": { + "ownedGames": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyGameInResponse" + } + ] + }, + "memberOf": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyPlayerGroupInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "playerGroups": "#/components/schemas/relationshipsInPlayerGroupResponse", + "players": "#/components/schemas/relationshipsInPlayerResponse" + } + }, + "x-abstract": true + }, + "resourceInCreateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "games": "#/components/schemas/dataInCreateGameRequest", + "playerGroups": "#/components/schemas/dataInCreatePlayerGroupRequest", + "players": "#/components/schemas/dataInCreatePlayerRequest" + } + }, + "x-abstract": true + }, + "resourceInResponse": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "games": "#/components/schemas/dataInGameResponse", + "playerGroups": "#/components/schemas/dataInPlayerGroupResponse", + "players": "#/components/schemas/dataInPlayerResponse" + } + }, + "x-abstract": true + }, + "resourceLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceType": { + "enum": [ + "games", + "playerGroups", + "players" + ], + "type": "string" + }, + "toManyGameInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/gameIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyGameInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/gameIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyPlayerGroupInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/playerGroupIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyPlayerGroupInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/playerGroupIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyPlayerInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/playerIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyPlayerInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/playerIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/test/OpenApiTests/ClientIdGenerationModes/Player.cs b/test/OpenApiTests/ClientIdGenerationModes/Player.cs new file mode 100644 index 0000000000..e150af5756 --- /dev/null +++ b/test/OpenApiTests/ClientIdGenerationModes/Player.cs @@ -0,0 +1,22 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.ClientIdGenerationModes; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.ClientIdGenerationModes", ClientIdGeneration = ClientIdGenerationMode.Required, + GenerateControllerEndpoints = JsonApiEndpoints.Post)] +public sealed class Player : Identifiable +{ + [Attr] + public string UserName { get; set; } = null!; + + [HasMany] + public List OwnedGames { get; set; } = []; + + [HasMany] + public List MemberOf { get; set; } = []; +} diff --git a/test/OpenApiTests/ClientIdGenerationModes/PlayerGroup.cs b/test/OpenApiTests/ClientIdGenerationModes/PlayerGroup.cs new file mode 100644 index 0000000000..9f2547a61f --- /dev/null +++ b/test/OpenApiTests/ClientIdGenerationModes/PlayerGroup.cs @@ -0,0 +1,19 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.ClientIdGenerationModes; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.ClientIdGenerationModes", ClientIdGeneration = ClientIdGenerationMode.Forbidden, + GenerateControllerEndpoints = JsonApiEndpoints.Post)] +public sealed class PlayerGroup : Identifiable +{ + [Attr] + public string Name { get; set; } = null!; + + [HasMany] + public List Players { get; set; } = []; +} diff --git a/test/OpenApiTests/Documentation/DocumentationDbContext.cs b/test/OpenApiTests/Documentation/DocumentationDbContext.cs new file mode 100644 index 0000000000..5d6c24b9ce --- /dev/null +++ b/test/OpenApiTests/Documentation/DocumentationDbContext.cs @@ -0,0 +1,26 @@ +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; +using TestBuildingBlocks; + +// @formatter:wrap_chained_method_calls chop_always + +namespace OpenApiTests.Documentation; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public sealed class DocumentationDbContext(DbContextOptions options) + : TestableDbContext(options) +{ + public DbSet Skyscrapers => Set(); + public DbSet Elevators => Set(); + public DbSet Spaces => Set(); + + protected override void OnModelCreating(ModelBuilder builder) + { + builder.Entity() + .HasOne(skyscraper => skyscraper.Elevator) + .WithOne(elevator => elevator.ExistsIn) + .HasForeignKey("ElevatorId"); + + base.OnModelCreating(builder); + } +} diff --git a/test/OpenApiTests/Documentation/DocumentationStartup.cs b/test/OpenApiTests/Documentation/DocumentationStartup.cs new file mode 100644 index 0000000000..318343f24e --- /dev/null +++ b/test/OpenApiTests/Documentation/DocumentationStartup.cs @@ -0,0 +1,42 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; +using TestBuildingBlocks; + +namespace OpenApiTests.Documentation; + +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +public sealed class DocumentationStartup : OpenApiStartup + where TDbContext : TestableDbContext +{ + protected override void SetJsonApiOptions(JsonApiOptions options) + { + base.SetJsonApiOptions(options); + + options.ClientIdGeneration = ClientIdGenerationMode.Allowed; + } + + protected override void SetupSwaggerGenAction(SwaggerGenOptions options) + { + options.SwaggerDoc("v1", new OpenApiInfo + { + Version = "v1", + Title = "Skyscrapers of the world", + Description = "A JSON:API service for managing skyscrapers.", + Contact = new OpenApiContact + { + Name = "Report issues", + Url = new Uri("https://github.com/json-api-dotnet/JsonApiDotNetCore/issues") + }, + License = new OpenApiLicense + { + Name = "MIT License", + Url = new Uri("https://licenses.nuget.org/MIT") + } + }); + + base.SetupSwaggerGenAction(options); + } +} diff --git a/test/OpenApiTests/Documentation/DocumentationTests.cs b/test/OpenApiTests/Documentation/DocumentationTests.cs new file mode 100644 index 0000000000..0dfc35d908 --- /dev/null +++ b/test/OpenApiTests/Documentation/DocumentationTests.cs @@ -0,0 +1,740 @@ +using System.Text.Json; +using FluentAssertions; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +// @formatter:max_line_length 250 + +namespace OpenApiTests.Documentation; + +public sealed class DocumentationTests : IClassFixture, DocumentationDbContext>> +{ + private const string ResourceTextQueryString = + "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters."; + + private const string RelationshipTextQueryString = + "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters."; + + private readonly OpenApiTestContext, DocumentationDbContext> _testContext; + + public DocumentationTests(OpenApiTestContext, DocumentationDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + + testContext.SetTestOutputHelper(testOutputHelper); + } + + [Fact] + public async Task API_is_documented() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("info").With(infoElement => + { + infoElement.Should().HaveProperty("title", "Skyscrapers of the world"); + infoElement.Should().HaveProperty("description", "A JSON:API service for managing skyscrapers."); + infoElement.Should().HaveProperty("version", "v1"); + + infoElement.Should().ContainPath("contact").With(contactElement => + { + contactElement.Should().HaveProperty("name", "Report issues"); + contactElement.Should().HaveProperty("url", "https://github.com/json-api-dotnet/JsonApiDotNetCore/issues"); + }); + + infoElement.Should().ContainPath("license").With(contactElement => + { + contactElement.Should().HaveProperty("name", "MIT License"); + contactElement.Should().HaveProperty("url", "https://licenses.nuget.org/MIT"); + }); + }); + } + + [Fact] + public async Task Endpoints_are_documented() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./skyscrapers").With(skyscrapersElement => + { + skyscrapersElement.Should().ContainPath("get").With(getElement => + { + getElement.Should().HaveProperty("summary", "Retrieves a collection of skyscrapers."); + + getElement.Should().ContainPath("parameters").With(parametersElement => + { + parametersElement.EnumerateArray().Should().HaveCount(2); + parametersElement.Should().HaveProperty("[0].in", "query"); + parametersElement.Should().HaveProperty("[0].description", ResourceTextQueryString); + parametersElement.Should().HaveProperty("[1].name", "If-None-Match"); + parametersElement.Should().HaveProperty("[1].in", "header"); + parametersElement.Should().HaveProperty("[1].description", "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint."); + }); + + getElement.Should().ContainPath("responses").With(responsesElement => + { + responsesElement.EnumerateObject().Should().HaveCount(3); + responsesElement.Should().HaveProperty("200.description", "Successfully returns the found skyscrapers, or an empty array if none were found."); + responsesElement.Should().HaveProperty("200.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("304.description", "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header."); + responsesElement.Should().HaveProperty("304.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("400.description", "The query string is invalid."); + }); + }); + + skyscrapersElement.Should().ContainPath("head").With(headElement => + { + headElement.Should().HaveProperty("summary", "Retrieves a collection of skyscrapers without returning them."); + headElement.Should().HaveProperty("description", "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched."); + + headElement.Should().ContainPath("parameters").With(parametersElement => + { + parametersElement.EnumerateArray().Should().HaveCount(2); + parametersElement.Should().HaveProperty("[0].in", "query"); + parametersElement.Should().HaveProperty("[0].description", ResourceTextQueryString); + parametersElement.Should().HaveProperty("[1].name", "If-None-Match"); + parametersElement.Should().HaveProperty("[1].in", "header"); + parametersElement.Should().HaveProperty("[1].description", "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint."); + }); + + headElement.Should().ContainPath("responses").With(responsesElement => + { + responsesElement.EnumerateObject().Should().HaveCount(3); + responsesElement.Should().HaveProperty("200.description", "The operation completed successfully."); + responsesElement.Should().HaveProperty("200.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("200.headers.Content-Length.description", "Size of the HTTP response body, in bytes."); + responsesElement.Should().HaveProperty("304.description", "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header."); + responsesElement.Should().HaveProperty("304.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("400.description", "The query string is invalid."); + }); + }); + + skyscrapersElement.Should().ContainPath("post").With(postElement => + { + postElement.Should().HaveProperty("summary", "Creates a new skyscraper."); + + postElement.Should().ContainPath("parameters").With(parametersElement => + { + parametersElement.EnumerateArray().Should().HaveCount(1); + parametersElement.Should().HaveProperty("[0].in", "query"); + parametersElement.Should().HaveProperty("[0].description", ResourceTextQueryString); + }); + + postElement.Should().HaveProperty("requestBody.description", "The attributes and relationships of the skyscraper to create."); + + postElement.Should().ContainPath("responses").With(responsesElement => + { + responsesElement.EnumerateObject().Should().HaveCount(6); + responsesElement.Should().HaveProperty("201.description", "The skyscraper was successfully created, which resulted in additional changes. The newly created skyscraper is returned."); + responsesElement.Should().HaveProperty("201.headers.Location.description", "The URL at which the newly created skyscraper can be retrieved."); + responsesElement.Should().HaveProperty("204.description", "The skyscraper was successfully created, which did not result in additional changes."); + responsesElement.Should().HaveProperty("400.description", "The query string is invalid or the request body is missing or malformed."); + responsesElement.Should().HaveProperty("404.description", "A related resource does not exist."); + responsesElement.Should().HaveProperty("409.description", "The request body contains conflicting information or another resource with the same ID already exists."); + responsesElement.Should().HaveProperty("422.description", "Validation of the request body failed."); + }); + }); + }); + + document.Should().ContainPath("paths./skyscrapers/{id}").With(idElement => + { + idElement.Should().ContainPath("get").With(getElement => + { + getElement.Should().HaveProperty("summary", "Retrieves an individual skyscraper by its identifier."); + + getElement.Should().ContainPath("parameters").With(parametersElement => + { + parametersElement.EnumerateArray().Should().HaveCount(3); + parametersElement.Should().HaveProperty("[0].in", "path"); + parametersElement.Should().HaveProperty("[0].description", "The identifier of the skyscraper to retrieve."); + parametersElement.Should().HaveProperty("[1].in", "query"); + parametersElement.Should().HaveProperty("[1].description", ResourceTextQueryString); + parametersElement.Should().HaveProperty("[2].name", "If-None-Match"); + parametersElement.Should().HaveProperty("[2].in", "header"); + parametersElement.Should().HaveProperty("[2].description", "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint."); + }); + + getElement.Should().ContainPath("responses").With(responsesElement => + { + responsesElement.EnumerateObject().Should().HaveCount(4); + responsesElement.Should().HaveProperty("200.description", "Successfully returns the found skyscraper."); + responsesElement.Should().HaveProperty("200.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("304.description", "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header."); + responsesElement.Should().HaveProperty("304.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("400.description", "The query string is invalid."); + responsesElement.Should().HaveProperty("404.description", "The skyscraper does not exist."); + }); + }); + + idElement.Should().ContainPath("head").With(headElement => + { + headElement.Should().HaveProperty("summary", "Retrieves an individual skyscraper by its identifier without returning it."); + headElement.Should().HaveProperty("description", "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched."); + + headElement.Should().ContainPath("parameters").With(parametersElement => + { + parametersElement.EnumerateArray().Should().HaveCount(3); + parametersElement.Should().HaveProperty("[0].in", "path"); + parametersElement.Should().HaveProperty("[0].description", "The identifier of the skyscraper to retrieve."); + parametersElement.Should().HaveProperty("[1].in", "query"); + parametersElement.Should().HaveProperty("[1].description", ResourceTextQueryString); + parametersElement.Should().HaveProperty("[2].name", "If-None-Match"); + parametersElement.Should().HaveProperty("[2].in", "header"); + parametersElement.Should().HaveProperty("[2].description", "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint."); + }); + + headElement.Should().ContainPath("responses").With(responsesElement => + { + responsesElement.EnumerateObject().Should().HaveCount(4); + responsesElement.Should().HaveProperty("200.description", "The operation completed successfully."); + responsesElement.Should().HaveProperty("200.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("200.headers.Content-Length.description", "Size of the HTTP response body, in bytes."); + responsesElement.Should().HaveProperty("304.description", "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header."); + responsesElement.Should().HaveProperty("304.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("400.description", "The query string is invalid."); + responsesElement.Should().HaveProperty("404.description", "The skyscraper does not exist."); + }); + }); + + idElement.Should().ContainPath("patch").With(patchElement => + { + patchElement.Should().HaveProperty("summary", "Updates an existing skyscraper."); + + patchElement.Should().ContainPath("parameters").With(parametersElement => + { + parametersElement.EnumerateArray().Should().HaveCount(2); + parametersElement.Should().HaveProperty("[0].in", "path"); + parametersElement.Should().HaveProperty("[0].description", "The identifier of the skyscraper to update."); + parametersElement.Should().HaveProperty("[1].in", "query"); + parametersElement.Should().HaveProperty("[1].description", ResourceTextQueryString); + }); + + patchElement.Should().HaveProperty("requestBody.description", "The attributes and relationships of the skyscraper to update. Omitted fields are left unchanged."); + + patchElement.Should().ContainPath("responses").With(responsesElement => + { + responsesElement.EnumerateObject().Should().HaveCount(6); + responsesElement.Should().HaveProperty("200.description", "The skyscraper was successfully updated, which resulted in additional changes. The updated skyscraper is returned."); + responsesElement.Should().HaveProperty("204.description", "The skyscraper was successfully updated, which did not result in additional changes."); + responsesElement.Should().HaveProperty("400.description", "The query string is invalid or the request body is missing or malformed."); + responsesElement.Should().HaveProperty("404.description", "The skyscraper or a related resource does not exist."); + responsesElement.Should().HaveProperty("409.description", "A resource type or identifier in the request body is incompatible."); + responsesElement.Should().HaveProperty("422.description", "Validation of the request body failed."); + }); + }); + + idElement.Should().ContainPath("delete").With(deleteElement => + { + deleteElement.Should().HaveProperty("summary", "Deletes an existing skyscraper by its identifier."); + + deleteElement.Should().ContainPath("parameters").With(parametersElement => + { + parametersElement.EnumerateArray().Should().HaveCount(1); + parametersElement.Should().HaveProperty("[0].in", "path"); + parametersElement.Should().HaveProperty("[0].description", "The identifier of the skyscraper to delete."); + }); + + deleteElement.Should().ContainPath("responses").With(responsesElement => + { + responsesElement.EnumerateObject().Should().HaveCount(2); + responsesElement.Should().HaveProperty("204.description", "The skyscraper was successfully deleted."); + responsesElement.Should().HaveProperty("404.description", "The skyscraper does not exist."); + }); + }); + }); + + document.Should().ContainPath("paths./skyscrapers/{id}/elevator").With(elevatorElement => + { + elevatorElement.Should().ContainPath("get").With(getElement => + { + getElement.Should().HaveProperty("summary", "Retrieves the related elevator of an individual skyscraper's elevator relationship."); + + getElement.Should().ContainPath("parameters").With(parametersElement => + { + parametersElement.EnumerateArray().Should().HaveCount(3); + parametersElement.Should().HaveProperty("[0].in", "path"); + parametersElement.Should().HaveProperty("[0].description", "The identifier of the skyscraper whose related elevator to retrieve."); + parametersElement.Should().HaveProperty("[1].in", "query"); + parametersElement.Should().HaveProperty("[1].description", ResourceTextQueryString); + parametersElement.Should().HaveProperty("[2].name", "If-None-Match"); + parametersElement.Should().HaveProperty("[2].in", "header"); + parametersElement.Should().HaveProperty("[2].description", "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint."); + }); + + getElement.Should().ContainPath("responses").With(responsesElement => + { + responsesElement.EnumerateObject().Should().HaveCount(4); + responsesElement.Should().HaveProperty("200.description", "Successfully returns the found elevator, or `null` if it was not found."); + responsesElement.Should().HaveProperty("200.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("304.description", "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header."); + responsesElement.Should().HaveProperty("304.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("400.description", "The query string is invalid."); + responsesElement.Should().HaveProperty("404.description", "The skyscraper does not exist."); + }); + }); + + elevatorElement.Should().ContainPath("head").With(headElement => + { + headElement.Should().HaveProperty("summary", "Retrieves the related elevator of an individual skyscraper's elevator relationship without returning it."); + headElement.Should().HaveProperty("description", "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched."); + + headElement.Should().ContainPath("parameters").With(parametersElement => + { + parametersElement.EnumerateArray().Should().HaveCount(3); + parametersElement.Should().HaveProperty("[0].in", "path"); + parametersElement.Should().HaveProperty("[0].description", "The identifier of the skyscraper whose related elevator to retrieve."); + parametersElement.Should().HaveProperty("[1].in", "query"); + parametersElement.Should().HaveProperty("[1].description", ResourceTextQueryString); + parametersElement.Should().HaveProperty("[2].name", "If-None-Match"); + parametersElement.Should().HaveProperty("[2].in", "header"); + parametersElement.Should().HaveProperty("[2].description", "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint."); + }); + + headElement.Should().ContainPath("responses").With(responsesElement => + { + responsesElement.EnumerateObject().Should().HaveCount(4); + responsesElement.Should().HaveProperty("200.description", "The operation completed successfully."); + responsesElement.Should().HaveProperty("200.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("200.headers.Content-Length.description", "Size of the HTTP response body, in bytes."); + responsesElement.Should().HaveProperty("304.description", "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header."); + responsesElement.Should().HaveProperty("304.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("400.description", "The query string is invalid."); + responsesElement.Should().HaveProperty("404.description", "The skyscraper does not exist."); + }); + }); + }); + + document.Should().ContainPath("paths./skyscrapers/{id}/relationships/elevator").With(elevatorElement => + { + elevatorElement.Should().ContainPath("get").With(getElement => + { + getElement.Should().HaveProperty("summary", "Retrieves the related elevator identity of an individual skyscraper's elevator relationship."); + + getElement.Should().ContainPath("parameters").With(parametersElement => + { + parametersElement.EnumerateArray().Should().HaveCount(3); + parametersElement.Should().HaveProperty("[0].in", "path"); + parametersElement.Should().HaveProperty("[0].description", "The identifier of the skyscraper whose related elevator identity to retrieve."); + parametersElement.Should().HaveProperty("[1].in", "query"); + parametersElement.Should().HaveProperty("[1].description", RelationshipTextQueryString); + parametersElement.Should().HaveProperty("[2].name", "If-None-Match"); + parametersElement.Should().HaveProperty("[2].in", "header"); + parametersElement.Should().HaveProperty("[2].description", "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint."); + }); + + getElement.Should().ContainPath("responses").With(responsesElement => + { + responsesElement.EnumerateObject().Should().HaveCount(4); + responsesElement.Should().HaveProperty("200.description", "Successfully returns the found elevator identity, or `null` if it was not found."); + responsesElement.Should().HaveProperty("200.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("304.description", "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header."); + responsesElement.Should().HaveProperty("304.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("400.description", "The query string is invalid."); + responsesElement.Should().HaveProperty("404.description", "The skyscraper does not exist."); + }); + }); + + elevatorElement.Should().ContainPath("head").With(headElement => + { + headElement.Should().HaveProperty("summary", "Retrieves the related elevator identity of an individual skyscraper's elevator relationship without returning it."); + headElement.Should().HaveProperty("description", "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched."); + + headElement.Should().ContainPath("parameters").With(parametersElement => + { + parametersElement.EnumerateArray().Should().HaveCount(3); + parametersElement.Should().HaveProperty("[0].in", "path"); + parametersElement.Should().HaveProperty("[0].description", "The identifier of the skyscraper whose related elevator identity to retrieve."); + parametersElement.Should().HaveProperty("[1].in", "query"); + parametersElement.Should().HaveProperty("[1].description", RelationshipTextQueryString); + parametersElement.Should().HaveProperty("[2].name", "If-None-Match"); + parametersElement.Should().HaveProperty("[2].in", "header"); + parametersElement.Should().HaveProperty("[2].description", "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint."); + }); + + headElement.Should().ContainPath("responses").With(responsesElement => + { + responsesElement.EnumerateObject().Should().HaveCount(4); + responsesElement.Should().HaveProperty("200.description", "The operation completed successfully."); + responsesElement.Should().HaveProperty("200.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("200.headers.Content-Length.description", "Size of the HTTP response body, in bytes."); + responsesElement.Should().HaveProperty("304.description", "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header."); + responsesElement.Should().HaveProperty("304.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("400.description", "The query string is invalid."); + responsesElement.Should().HaveProperty("404.description", "The skyscraper does not exist."); + }); + }); + + elevatorElement.Should().ContainPath("patch").With(patchElement => + { + patchElement.Should().HaveProperty("summary", "Clears or assigns an existing elevator to the elevator relationship of an individual skyscraper."); + + patchElement.Should().ContainPath("parameters").With(parametersElement => + { + parametersElement.EnumerateArray().Should().HaveCount(1); + parametersElement.Should().HaveProperty("[0].in", "path"); + parametersElement.Should().HaveProperty("[0].description", "The identifier of the skyscraper whose elevator relationship to assign or clear."); + }); + + patchElement.Should().HaveProperty("requestBody.description", "The identity of the elevator to assign to the elevator relationship, or `null` to clear the relationship."); + + patchElement.Should().ContainPath("responses").With(responsesElement => + { + responsesElement.EnumerateObject().Should().HaveCount(5); + responsesElement.Should().HaveProperty("204.description", "The elevator relationship was successfully updated, which did not result in additional changes."); + responsesElement.Should().HaveProperty("400.description", "The request body is missing or malformed."); + responsesElement.Should().HaveProperty("404.description", "The skyscraper or a related resource does not exist."); + responsesElement.Should().HaveProperty("409.description", "The request body contains conflicting information or another resource with the same ID already exists."); + responsesElement.Should().HaveProperty("422.description", "Validation of the request body failed."); + }); + }); + }); + + document.Should().ContainPath("paths./skyscrapers/{id}/spaces").With(spacesElement => + { + spacesElement.Should().ContainPath("get").With(getElement => + { + getElement.Should().HaveProperty("summary", "Retrieves the related spaces of an individual skyscraper's spaces relationship."); + + getElement.Should().ContainPath("parameters").With(parametersElement => + { + parametersElement.EnumerateArray().Should().HaveCount(3); + parametersElement.Should().HaveProperty("[0].in", "path"); + parametersElement.Should().HaveProperty("[0].description", "The identifier of the skyscraper whose related spaces to retrieve."); + parametersElement.Should().HaveProperty("[1].in", "query"); + parametersElement.Should().HaveProperty("[1].description", ResourceTextQueryString); + parametersElement.Should().HaveProperty("[2].name", "If-None-Match"); + parametersElement.Should().HaveProperty("[2].in", "header"); + parametersElement.Should().HaveProperty("[2].description", "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint."); + }); + + getElement.Should().ContainPath("responses").With(responsesElement => + { + responsesElement.EnumerateObject().Should().HaveCount(4); + responsesElement.Should().HaveProperty("200.description", "Successfully returns the found spaces, or an empty array if none were found."); + responsesElement.Should().HaveProperty("200.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("304.description", "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header."); + responsesElement.Should().HaveProperty("304.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("400.description", "The query string is invalid."); + responsesElement.Should().HaveProperty("404.description", "The skyscraper does not exist."); + }); + }); + + spacesElement.Should().ContainPath("head").With(headElement => + { + headElement.Should().HaveProperty("summary", "Retrieves the related spaces of an individual skyscraper's spaces relationship without returning them."); + headElement.Should().HaveProperty("description", "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched."); + + headElement.Should().ContainPath("parameters").With(parametersElement => + { + parametersElement.EnumerateArray().Should().HaveCount(3); + parametersElement.Should().HaveProperty("[0].in", "path"); + parametersElement.Should().HaveProperty("[0].description", "The identifier of the skyscraper whose related spaces to retrieve."); + parametersElement.Should().HaveProperty("[1].in", "query"); + parametersElement.Should().HaveProperty("[1].description", ResourceTextQueryString); + parametersElement.Should().HaveProperty("[2].name", "If-None-Match"); + parametersElement.Should().HaveProperty("[2].in", "header"); + parametersElement.Should().HaveProperty("[2].description", "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint."); + }); + + headElement.Should().ContainPath("responses").With(responsesElement => + { + responsesElement.EnumerateObject().Should().HaveCount(4); + responsesElement.Should().HaveProperty("200.description", "The operation completed successfully."); + responsesElement.Should().HaveProperty("200.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("200.headers.Content-Length.description", "Size of the HTTP response body, in bytes."); + responsesElement.Should().HaveProperty("304.description", "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header."); + responsesElement.Should().HaveProperty("304.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("400.description", "The query string is invalid."); + responsesElement.Should().HaveProperty("404.description", "The skyscraper does not exist."); + }); + }); + }); + + document.Should().ContainPath("paths./skyscrapers/{id}/relationships/spaces").With(spacesElement => + { + spacesElement.Should().ContainPath("get").With(getElement => + { + getElement.Should().HaveProperty("summary", "Retrieves the related space identities of an individual skyscraper's spaces relationship."); + + getElement.Should().ContainPath("parameters").With(parametersElement => + { + parametersElement.EnumerateArray().Should().HaveCount(3); + parametersElement.Should().HaveProperty("[0].in", "path"); + parametersElement.Should().HaveProperty("[0].description", "The identifier of the skyscraper whose related space identities to retrieve."); + parametersElement.Should().HaveProperty("[1].in", "query"); + parametersElement.Should().HaveProperty("[1].description", RelationshipTextQueryString); + parametersElement.Should().HaveProperty("[2].name", "If-None-Match"); + parametersElement.Should().HaveProperty("[2].in", "header"); + parametersElement.Should().HaveProperty("[2].description", "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint."); + }); + + getElement.Should().ContainPath("responses").With(responsesElement => + { + responsesElement.EnumerateObject().Should().HaveCount(4); + responsesElement.Should().HaveProperty("200.description", "Successfully returns the found space identities, or an empty array if none were found."); + responsesElement.Should().HaveProperty("200.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("304.description", "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header."); + responsesElement.Should().HaveProperty("304.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("400.description", "The query string is invalid."); + responsesElement.Should().HaveProperty("404.description", "The skyscraper does not exist."); + }); + }); + + spacesElement.Should().ContainPath("head").With(headElement => + { + headElement.Should().HaveProperty("summary", "Retrieves the related space identities of an individual skyscraper's spaces relationship without returning them."); + headElement.Should().HaveProperty("description", "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched."); + + headElement.Should().ContainPath("parameters").With(parametersElement => + { + parametersElement.EnumerateArray().Should().HaveCount(3); + parametersElement.Should().HaveProperty("[0].in", "path"); + parametersElement.Should().HaveProperty("[0].description", "The identifier of the skyscraper whose related space identities to retrieve."); + parametersElement.Should().HaveProperty("[1].in", "query"); + parametersElement.Should().HaveProperty("[1].description", RelationshipTextQueryString); + parametersElement.Should().HaveProperty("[2].name", "If-None-Match"); + parametersElement.Should().HaveProperty("[2].in", "header"); + parametersElement.Should().HaveProperty("[2].description", "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint."); + }); + + headElement.Should().ContainPath("responses").With(responsesElement => + { + responsesElement.EnumerateObject().Should().HaveCount(4); + responsesElement.Should().HaveProperty("200.description", "The operation completed successfully."); + responsesElement.Should().HaveProperty("200.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("200.headers.Content-Length.description", "Size of the HTTP response body, in bytes."); + responsesElement.Should().HaveProperty("304.description", "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header."); + responsesElement.Should().HaveProperty("304.headers.ETag.description", "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + responsesElement.Should().HaveProperty("400.description", "The query string is invalid."); + responsesElement.Should().HaveProperty("404.description", "The skyscraper does not exist."); + }); + }); + + spacesElement.Should().ContainPath("post").With(postElement => + { + postElement.Should().HaveProperty("summary", "Adds existing spaces to the spaces relationship of an individual skyscraper."); + + postElement.Should().ContainPath("parameters").With(parametersElement => + { + parametersElement.EnumerateArray().Should().HaveCount(1); + parametersElement.Should().HaveProperty("[0].in", "path"); + parametersElement.Should().HaveProperty("[0].description", "The identifier of the skyscraper to add spaces to."); + }); + + postElement.Should().HaveProperty("requestBody.description", "The identities of the spaces to add to the spaces relationship."); + + postElement.Should().ContainPath("responses").With(responsesElement => + { + responsesElement.EnumerateObject().Should().HaveCount(5); + responsesElement.Should().HaveProperty("204.description", "The spaces were successfully added, which did not result in additional changes."); + responsesElement.Should().HaveProperty("400.description", "The request body is missing or malformed."); + responsesElement.Should().HaveProperty("404.description", "The skyscraper or a related resource does not exist."); + responsesElement.Should().HaveProperty("409.description", "The request body contains conflicting information or another resource with the same ID already exists."); + responsesElement.Should().HaveProperty("422.description", "Validation of the request body failed."); + }); + }); + + spacesElement.Should().ContainPath("patch").With(patchElement => + { + patchElement.Should().HaveProperty("summary", "Assigns existing spaces to the spaces relationship of an individual skyscraper."); + + patchElement.Should().ContainPath("parameters").With(parametersElement => + { + parametersElement.EnumerateArray().Should().HaveCount(1); + parametersElement.Should().HaveProperty("[0].in", "path"); + parametersElement.Should().HaveProperty("[0].description", "The identifier of the skyscraper whose spaces relationship to assign."); + }); + + patchElement.Should().HaveProperty("requestBody.description", "The identities of the spaces to assign to the spaces relationship, or an empty array to clear the relationship."); + + patchElement.Should().ContainPath("responses").With(responsesElement => + { + responsesElement.EnumerateObject().Should().HaveCount(5); + responsesElement.Should().HaveProperty("204.description", "The spaces relationship was successfully updated, which did not result in additional changes."); + responsesElement.Should().HaveProperty("400.description", "The request body is missing or malformed."); + responsesElement.Should().HaveProperty("404.description", "The skyscraper or a related resource does not exist."); + responsesElement.Should().HaveProperty("409.description", "The request body contains conflicting information or another resource with the same ID already exists."); + responsesElement.Should().HaveProperty("422.description", "Validation of the request body failed."); + }); + }); + + spacesElement.Should().ContainPath("delete").With(deleteElement => + { + deleteElement.Should().HaveProperty("summary", "Removes existing spaces from the spaces relationship of an individual skyscraper."); + + deleteElement.Should().ContainPath("parameters").With(parametersElement => + { + parametersElement.EnumerateArray().Should().HaveCount(1); + parametersElement.Should().HaveProperty("[0].in", "path"); + parametersElement.Should().HaveProperty("[0].description", "The identifier of the skyscraper to remove spaces from."); + }); + + deleteElement.Should().HaveProperty("requestBody.description", "The identities of the spaces to remove from the spaces relationship."); + + deleteElement.Should().ContainPath("responses").With(responsesElement => + { + responsesElement.EnumerateObject().Should().HaveCount(5); + responsesElement.Should().HaveProperty("204.description", "The spaces were successfully removed, which did not result in additional changes."); + responsesElement.Should().HaveProperty("400.description", "The request body is missing or malformed."); + responsesElement.Should().HaveProperty("404.description", "The skyscraper or a related resource does not exist."); + responsesElement.Should().HaveProperty("409.description", "The request body contains conflicting information or another resource with the same ID already exists."); + responsesElement.Should().HaveProperty("422.description", "Validation of the request body failed."); + }); + }); + }); + + document.Should().ContainPath("paths./operations").With(skyscrapersElement => + { + skyscrapersElement.Should().ContainPath("post").With(postElement => + { + postElement.Should().HaveProperty("summary", "Performs multiple mutations in a linear and atomic manner."); + + postElement.Should().HaveProperty("requestBody.description", "An array of mutation operations. For syntax, see the [Atomic Operations documentation](https://jsonapi.org/ext/atomic/)."); + + postElement.Should().ContainPath("responses").With(responsesElement => + { + responsesElement.EnumerateObject().Should().HaveCount(7); + responsesElement.Should().HaveProperty("200.description", "All operations were successfully applied, which resulted in additional changes."); + responsesElement.Should().HaveProperty("204.description", "All operations were successfully applied, which did not result in additional changes."); + responsesElement.Should().HaveProperty("400.description", "The request body is missing or malformed."); + responsesElement.Should().HaveProperty("403.description", "An operation is not accessible or a client-generated ID is used."); + responsesElement.Should().HaveProperty("404.description", "A resource or a related resource does not exist."); + responsesElement.Should().HaveProperty("409.description", "The request body contains conflicting information or another resource with the same ID already exists."); + responsesElement.Should().HaveProperty("422.description", "Validation of the request body failed."); + }); + }); + }); + } + + [Fact] + public async Task Resource_types_are_documented() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas").With(schemasElement => + { + schemasElement.Should().HaveProperty("dataInUpdateElevatorRequest.description", "An elevator within a skyscraper."); + schemasElement.Should().HaveProperty("dataInCreateElevatorRequest.description", "An elevator within a skyscraper."); + schemasElement.Should().HaveProperty("dataInElevatorResponse.description", "An elevator within a skyscraper."); + + schemasElement.Should().HaveProperty("dataInUpdateSkyscraperRequest.description", "A tall, continuously habitable building having multiple floors."); + schemasElement.Should().HaveProperty("dataInCreateSkyscraperRequest.description", "A tall, continuously habitable building having multiple floors."); + schemasElement.Should().HaveProperty("dataInSkyscraperResponse.description", "A tall, continuously habitable building having multiple floors."); + + schemasElement.Should().HaveProperty("dataInUpdateSpaceRequest.description", "A space within a skyscraper, such as an office, hotel, residential space, or retail space."); + schemasElement.Should().HaveProperty("dataInCreateSpaceRequest.description", "A space within a skyscraper, such as an office, hotel, residential space, or retail space."); + schemasElement.Should().HaveProperty("dataInSpaceResponse.description", "A space within a skyscraper, such as an office, hotel, residential space, or retail space."); + }); + } + + [Fact] + public async Task Attributes_are_documented() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas").With(schemasElement => + { + schemasElement.Should().HaveProperty("attributesInUpdateElevatorRequest.allOf[1].properties.floorCount.description", "The number of floors this elevator provides access to."); + schemasElement.Should().HaveProperty("attributesInCreateElevatorRequest.allOf[1].properties.floorCount.description", "The number of floors this elevator provides access to."); + schemasElement.Should().HaveProperty("attributesInElevatorResponse.allOf[1].properties.floorCount.description", "The number of floors this elevator provides access to."); + + schemasElement.Should().HaveProperty("attributesInUpdateSkyscraperRequest.allOf[1].properties.heightInMeters.description", "The height of this building, in meters."); + schemasElement.Should().HaveProperty("attributesInCreateSkyscraperRequest.allOf[1].properties.heightInMeters.description", "The height of this building, in meters."); + schemasElement.Should().HaveProperty("attributesInSkyscraperResponse.allOf[1].properties.heightInMeters.description", "The height of this building, in meters."); + + schemasElement.Should().ContainPath("attributesInUpdateSpaceRequest.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().HaveProperty("floorNumber.description", "The floor number on which this space resides."); + propertiesElement.Should().HaveProperty("kind.description", "The kind of this space."); + }); + + schemasElement.Should().ContainPath("attributesInCreateSpaceRequest.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().HaveProperty("floorNumber.description", "The floor number on which this space resides."); + propertiesElement.Should().HaveProperty("kind.description", "The kind of this space."); + }); + + schemasElement.Should().ContainPath("attributesInSpaceResponse.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().HaveProperty("floorNumber.description", "The floor number on which this space resides."); + propertiesElement.Should().HaveProperty("kind.description", "The kind of this space."); + }); + }); + } + + [Fact] + public async Task Relationships_are_documented() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas").With(schemasElement => + { + schemasElement.Should().HaveProperty("relationshipsInUpdateElevatorRequest.allOf[1].properties.existsIn.description", "The skyscraper this elevator exists in."); + schemasElement.Should().HaveProperty("relationshipsInCreateElevatorRequest.allOf[1].properties.existsIn.description", "The skyscraper this elevator exists in."); + schemasElement.Should().HaveProperty("relationshipsInElevatorResponse.allOf[1].properties.existsIn.description", "The skyscraper this elevator exists in."); + + schemasElement.Should().ContainPath("relationshipsInUpdateSkyscraperRequest.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().HaveProperty("elevator.description", "An optional elevator within this building, providing access to spaces."); + propertiesElement.Should().HaveProperty("spaces.description", "The spaces within this building."); + }); + + schemasElement.Should().ContainPath("relationshipsInCreateSkyscraperRequest.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().HaveProperty("elevator.description", "An optional elevator within this building, providing access to spaces."); + propertiesElement.Should().HaveProperty("spaces.description", "The spaces within this building."); + }); + + schemasElement.Should().ContainPath("relationshipsInSkyscraperResponse.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().HaveProperty("elevator.description", "An optional elevator within this building, providing access to spaces."); + propertiesElement.Should().HaveProperty("spaces.description", "The spaces within this building."); + }); + + schemasElement.Should().HaveProperty("relationshipsInUpdateSpaceRequest.allOf[1].properties.existsIn.description", "The skyscraper this space exists in."); + schemasElement.Should().HaveProperty("relationshipsInCreateSpaceRequest.allOf[1].properties.existsIn.description", "The skyscraper this space exists in."); + schemasElement.Should().HaveProperty("relationshipsInSpaceResponse.allOf[1].properties.existsIn.description", "The skyscraper this space exists in."); + }); + } + + [Fact] + public async Task Enums_are_documented() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas").With(schemasElement => + { + schemasElement.Should().HaveProperty("spaceKind.description", "Lists the various kinds of spaces within a skyscraper."); + }); + } + + [Fact] + public async Task Forbidden_status_is_added_when_client_generated_IDs_are_disabled() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./elevators.post.responses").With(responsesElement => + { + responsesElement.Should().HaveProperty("403.description", "Client-generated IDs cannot be used at this endpoint."); + }); + } +} diff --git a/test/OpenApiTests/Documentation/Elevator.cs b/test/OpenApiTests/Documentation/Elevator.cs new file mode 100644 index 0000000000..c739454c55 --- /dev/null +++ b/test/OpenApiTests/Documentation/Elevator.cs @@ -0,0 +1,26 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.Documentation; + +/// +/// An elevator within a skyscraper. +/// +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.Documentation", ClientIdGeneration = ClientIdGenerationMode.Forbidden)] +public sealed class Elevator : Identifiable +{ + /// + /// The number of floors this elevator provides access to. + /// + [Attr] + public int FloorCount { get; set; } + + /// + /// The skyscraper this elevator exists in. + /// + [HasOne] + public Skyscraper ExistsIn { get; set; } = null!; +} diff --git a/test/OpenApiTests/Documentation/ErrorResponseTests.cs b/test/OpenApiTests/Documentation/ErrorResponseTests.cs new file mode 100644 index 0000000000..0bae066f00 --- /dev/null +++ b/test/OpenApiTests/Documentation/ErrorResponseTests.cs @@ -0,0 +1,332 @@ +using System.Text.Json; +using FluentAssertions; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.Documentation; + +public sealed class ErrorResponseTests : IClassFixture, DocumentationDbContext>> +{ + private const string EscapedJsonApiMediaType = "['application/vnd.api+json; ext=openapi']"; + private const string EscapedOperationsMediaType = "['application/vnd.api+json; ext=atomic; ext=openapi']"; + + private readonly OpenApiTestContext, DocumentationDbContext> _testContext; + + public ErrorResponseTests(OpenApiTestContext, DocumentationDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + + testContext.SetTestOutputHelper(testOutputHelper); + } + + [Fact] + public async Task Applicable_error_status_codes_with_schema_are_provided_on_endpoints() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./skyscrapers").With(skyscrapersElement => + { + skyscrapersElement.Should().ContainPath("get.responses").With(responsesElement => + { + JsonProperty[] errorStatusCodeProperties = responsesElement.EnumerateObject().Where(IsErrorStatusCode).ToArray(); + errorStatusCodeProperties.Should().HaveCount(1); + + errorStatusCodeProperties[0].Name.Should().Be("400"); + + errorStatusCodeProperties.Should().AllSatisfy(property => + property.Value.Should().ContainPath($"content.{EscapedJsonApiMediaType}.schema.$ref").ShouldBeSchemaReferenceId("errorResponseDocument")); + }); + + skyscrapersElement.Should().ContainPath("head.responses").With(responsesElement => + { + JsonProperty[] errorStatusCodeProperties = responsesElement.EnumerateObject().Where(IsErrorStatusCode).ToArray(); + errorStatusCodeProperties.Should().HaveCount(1); + + errorStatusCodeProperties[0].Name.Should().Be("400"); + + errorStatusCodeProperties.Should().AllSatisfy(property => property.Value.Should().NotContainPath("content")); + }); + + skyscrapersElement.Should().ContainPath("post.responses").With(responsesElement => + { + JsonProperty[] errorStatusCodeProperties = responsesElement.EnumerateObject().Where(IsErrorStatusCode).ToArray(); + errorStatusCodeProperties.Should().HaveCount(4); + + errorStatusCodeProperties[0].Name.Should().Be("400"); + errorStatusCodeProperties[1].Name.Should().Be("404"); + errorStatusCodeProperties[2].Name.Should().Be("409"); + errorStatusCodeProperties[3].Name.Should().Be("422"); + + errorStatusCodeProperties.Should().AllSatisfy(property => + property.Value.Should().ContainPath($"content.{EscapedJsonApiMediaType}.schema.$ref").ShouldBeSchemaReferenceId("errorResponseDocument")); + }); + }); + + document.Should().ContainPath("paths./skyscrapers/{id}").With(idElement => + { + idElement.Should().ContainPath("get.responses").With(responsesElement => + { + JsonProperty[] errorStatusCodeProperties = responsesElement.EnumerateObject().Where(IsErrorStatusCode).ToArray(); + errorStatusCodeProperties.Should().HaveCount(2); + + errorStatusCodeProperties[0].Name.Should().Be("400"); + errorStatusCodeProperties[1].Name.Should().Be("404"); + + errorStatusCodeProperties.Should().AllSatisfy(property => + property.Value.Should().ContainPath($"content.{EscapedJsonApiMediaType}.schema.$ref").ShouldBeSchemaReferenceId("errorResponseDocument")); + }); + + idElement.Should().ContainPath("head.responses").With(responsesElement => + { + JsonProperty[] errorStatusCodeProperties = responsesElement.EnumerateObject().Where(IsErrorStatusCode).ToArray(); + errorStatusCodeProperties.Should().HaveCount(2); + + errorStatusCodeProperties[0].Name.Should().Be("400"); + errorStatusCodeProperties[1].Name.Should().Be("404"); + + errorStatusCodeProperties.Should().AllSatisfy(property => property.Value.Should().NotContainPath("content")); + }); + + idElement.Should().ContainPath("patch.responses").With(responsesElement => + { + JsonProperty[] errorStatusCodeProperties = responsesElement.EnumerateObject().Where(IsErrorStatusCode).ToArray(); + errorStatusCodeProperties.Should().HaveCount(4); + + errorStatusCodeProperties[0].Name.Should().Be("400"); + errorStatusCodeProperties[1].Name.Should().Be("404"); + errorStatusCodeProperties[2].Name.Should().Be("409"); + errorStatusCodeProperties[3].Name.Should().Be("422"); + + errorStatusCodeProperties.Should().AllSatisfy(property => + property.Value.Should().ContainPath($"content.{EscapedJsonApiMediaType}.schema.$ref").ShouldBeSchemaReferenceId("errorResponseDocument")); + }); + + idElement.Should().ContainPath("delete.responses").With(responsesElement => + { + JsonProperty[] errorStatusCodeProperties = responsesElement.EnumerateObject().Where(IsErrorStatusCode).ToArray(); + errorStatusCodeProperties.Should().HaveCount(1); + + errorStatusCodeProperties[0].Name.Should().Be("404"); + + errorStatusCodeProperties.Should().AllSatisfy(property => + property.Value.Should().ContainPath($"content.{EscapedJsonApiMediaType}.schema.$ref").ShouldBeSchemaReferenceId("errorResponseDocument")); + }); + }); + + document.Should().ContainPath("paths./skyscrapers/{id}/elevator").With(elevatorElement => + { + elevatorElement.Should().ContainPath("get.responses").With(responsesElement => + { + JsonProperty[] errorStatusCodeProperties = responsesElement.EnumerateObject().Where(IsErrorStatusCode).ToArray(); + errorStatusCodeProperties.Should().HaveCount(2); + + errorStatusCodeProperties[0].Name.Should().Be("400"); + errorStatusCodeProperties[1].Name.Should().Be("404"); + + errorStatusCodeProperties.Should().AllSatisfy(property => + property.Value.Should().ContainPath($"content.{EscapedJsonApiMediaType}.schema.$ref").ShouldBeSchemaReferenceId("errorResponseDocument")); + }); + + elevatorElement.Should().ContainPath("head.responses").With(responsesElement => + { + JsonProperty[] errorStatusCodeProperties = responsesElement.EnumerateObject().Where(IsErrorStatusCode).ToArray(); + errorStatusCodeProperties.Should().HaveCount(2); + + errorStatusCodeProperties[0].Name.Should().Be("400"); + errorStatusCodeProperties[1].Name.Should().Be("404"); + + errorStatusCodeProperties.Should().AllSatisfy(property => property.Value.Should().NotContainPath("content")); + }); + }); + + document.Should().ContainPath("paths./skyscrapers/{id}/relationships/elevator").With(elevatorElement => + { + elevatorElement.Should().ContainPath("get.responses").With(responsesElement => + { + JsonProperty[] errorStatusCodeProperties = responsesElement.EnumerateObject().Where(IsErrorStatusCode).ToArray(); + errorStatusCodeProperties.Should().HaveCount(2); + + errorStatusCodeProperties[0].Name.Should().Be("400"); + errorStatusCodeProperties[1].Name.Should().Be("404"); + + errorStatusCodeProperties.Should().AllSatisfy(property => + property.Value.Should().ContainPath($"content.{EscapedJsonApiMediaType}.schema.$ref").ShouldBeSchemaReferenceId("errorResponseDocument")); + }); + + elevatorElement.Should().ContainPath("head.responses").With(responsesElement => + { + JsonProperty[] errorStatusCodeProperties = responsesElement.EnumerateObject().Where(IsErrorStatusCode).ToArray(); + errorStatusCodeProperties.Should().HaveCount(2); + + errorStatusCodeProperties[0].Name.Should().Be("400"); + errorStatusCodeProperties[1].Name.Should().Be("404"); + + errorStatusCodeProperties.Should().AllSatisfy(property => property.Value.Should().NotContainPath("content")); + }); + + elevatorElement.Should().ContainPath("patch.responses").With(responsesElement => + { + JsonProperty[] errorStatusCodeProperties = responsesElement.EnumerateObject().Where(IsErrorStatusCode).ToArray(); + errorStatusCodeProperties.Should().HaveCount(4); + + errorStatusCodeProperties[0].Name.Should().Be("400"); + errorStatusCodeProperties[1].Name.Should().Be("404"); + errorStatusCodeProperties[2].Name.Should().Be("409"); + errorStatusCodeProperties[3].Name.Should().Be("422"); + + errorStatusCodeProperties.Should().AllSatisfy(property => + property.Value.Should().ContainPath($"content.{EscapedJsonApiMediaType}.schema.$ref").ShouldBeSchemaReferenceId("errorResponseDocument")); + }); + }); + + document.Should().ContainPath("paths./skyscrapers/{id}/spaces").With(spacesElement => + { + spacesElement.Should().ContainPath("get.responses").With(responsesElement => + { + JsonProperty[] errorStatusCodeProperties = responsesElement.EnumerateObject().Where(IsErrorStatusCode).ToArray(); + errorStatusCodeProperties.Should().HaveCount(2); + + errorStatusCodeProperties[0].Name.Should().Be("400"); + errorStatusCodeProperties[1].Name.Should().Be("404"); + + errorStatusCodeProperties.Should().AllSatisfy(property => + property.Value.Should().ContainPath($"content.{EscapedJsonApiMediaType}.schema.$ref").ShouldBeSchemaReferenceId("errorResponseDocument")); + }); + + spacesElement.Should().ContainPath("head.responses").With(responsesElement => + { + JsonProperty[] errorStatusCodeProperties = responsesElement.EnumerateObject().Where(IsErrorStatusCode).ToArray(); + errorStatusCodeProperties.Should().HaveCount(2); + + errorStatusCodeProperties[0].Name.Should().Be("400"); + errorStatusCodeProperties[1].Name.Should().Be("404"); + + errorStatusCodeProperties.Should().AllSatisfy(property => property.Value.Should().NotContainPath("content")); + }); + }); + + document.Should().ContainPath("paths./skyscrapers/{id}/relationships/spaces").With(spacesElement => + { + spacesElement.Should().ContainPath("get.responses").With(responsesElement => + { + JsonProperty[] errorStatusCodeProperties = responsesElement.EnumerateObject().Where(IsErrorStatusCode).ToArray(); + errorStatusCodeProperties.Should().HaveCount(2); + + errorStatusCodeProperties[0].Name.Should().Be("400"); + errorStatusCodeProperties[1].Name.Should().Be("404"); + + errorStatusCodeProperties.Should().AllSatisfy(property => + property.Value.Should().ContainPath($"content.{EscapedJsonApiMediaType}.schema.$ref").ShouldBeSchemaReferenceId("errorResponseDocument")); + }); + + spacesElement.Should().ContainPath("head.responses").With(responsesElement => + { + JsonProperty[] errorStatusCodeProperties = responsesElement.EnumerateObject().Where(IsErrorStatusCode).ToArray(); + errorStatusCodeProperties.Should().HaveCount(2); + + errorStatusCodeProperties[0].Name.Should().Be("400"); + errorStatusCodeProperties[1].Name.Should().Be("404"); + + errorStatusCodeProperties.Should().AllSatisfy(property => property.Value.Should().NotContainPath("content")); + }); + + spacesElement.Should().ContainPath("post.responses").With(responsesElement => + { + JsonProperty[] errorStatusCodeProperties = responsesElement.EnumerateObject().Where(IsErrorStatusCode).ToArray(); + errorStatusCodeProperties.Should().HaveCount(4); + + errorStatusCodeProperties[0].Name.Should().Be("400"); + errorStatusCodeProperties[1].Name.Should().Be("404"); + errorStatusCodeProperties[2].Name.Should().Be("409"); + errorStatusCodeProperties[3].Name.Should().Be("422"); + + errorStatusCodeProperties.Should().AllSatisfy(property => + property.Value.Should().ContainPath($"content.{EscapedJsonApiMediaType}.schema.$ref").ShouldBeSchemaReferenceId("errorResponseDocument")); + }); + + spacesElement.Should().ContainPath("patch.responses").With(responsesElement => + { + JsonProperty[] errorStatusCodeProperties = responsesElement.EnumerateObject().Where(IsErrorStatusCode).ToArray(); + errorStatusCodeProperties.Should().HaveCount(4); + + errorStatusCodeProperties[0].Name.Should().Be("400"); + errorStatusCodeProperties[1].Name.Should().Be("404"); + errorStatusCodeProperties[2].Name.Should().Be("409"); + errorStatusCodeProperties[3].Name.Should().Be("422"); + + errorStatusCodeProperties.Should().AllSatisfy(property => + property.Value.Should().ContainPath($"content.{EscapedJsonApiMediaType}.schema.$ref").ShouldBeSchemaReferenceId("errorResponseDocument")); + }); + + spacesElement.Should().ContainPath("delete.responses").With(responsesElement => + { + JsonProperty[] errorStatusCodeProperties = responsesElement.EnumerateObject().Where(IsErrorStatusCode).ToArray(); + errorStatusCodeProperties.Should().HaveCount(4); + + errorStatusCodeProperties[0].Name.Should().Be("400"); + errorStatusCodeProperties[1].Name.Should().Be("404"); + errorStatusCodeProperties[2].Name.Should().Be("409"); + errorStatusCodeProperties[3].Name.Should().Be("422"); + + errorStatusCodeProperties.Should().AllSatisfy(property => + property.Value.Should().ContainPath($"content.{EscapedJsonApiMediaType}.schema.$ref").ShouldBeSchemaReferenceId("errorResponseDocument")); + }); + }); + + document.Should().ContainPath("paths./operations").With(skyscrapersElement => + { + skyscrapersElement.Should().ContainPath("post.responses").With(responsesElement => + { + JsonProperty[] errorStatusCodeProperties = responsesElement.EnumerateObject().Where(IsErrorStatusCode).ToArray(); + errorStatusCodeProperties.Should().HaveCount(5); + + errorStatusCodeProperties[0].Name.Should().Be("400"); + errorStatusCodeProperties[1].Name.Should().Be("403"); + errorStatusCodeProperties[2].Name.Should().Be("404"); + errorStatusCodeProperties[3].Name.Should().Be("409"); + errorStatusCodeProperties[4].Name.Should().Be("422"); + + errorStatusCodeProperties.Should().AllSatisfy(property => + property.Value.Should().ContainPath($"content.{EscapedOperationsMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("errorResponseDocument")); + }); + }); + } + + [Fact] + public async Task Forbidden_status_is_added_when_client_generated_IDs_are_disabled() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./elevators.post.responses").With(responsesElement => + { + JsonProperty[] errorStatusCodeProperties = responsesElement.EnumerateObject().Where(IsErrorStatusCode).ToArray(); + errorStatusCodeProperties.Should().HaveCount(5); + + errorStatusCodeProperties[0].Name.Should().Be("400"); + errorStatusCodeProperties[1].Name.Should().Be("403"); + errorStatusCodeProperties[2].Name.Should().Be("404"); + errorStatusCodeProperties[3].Name.Should().Be("409"); + errorStatusCodeProperties[4].Name.Should().Be("422"); + + errorStatusCodeProperties.Should().AllSatisfy(property => + property.Value.Should().ContainPath($"content.{EscapedJsonApiMediaType}.schema.$ref").ShouldBeSchemaReferenceId("errorResponseDocument")); + }); + } + + private static bool IsErrorStatusCode(JsonProperty statusCodeProperty) + { + return int.TryParse(statusCodeProperty.Name, out int statusCodeValue) && statusCodeValue >= 400; + } +} diff --git a/test/OpenApiTests/Documentation/OperationsController.cs b/test/OpenApiTests/Documentation/OperationsController.cs new file mode 100644 index 0000000000..17129d3407 --- /dev/null +++ b/test/OpenApiTests/Documentation/OperationsController.cs @@ -0,0 +1,13 @@ +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.Resources; +using Microsoft.Extensions.Logging; + +namespace OpenApiTests.Documentation; + +public sealed class OperationsController( + IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, IOperationsProcessor processor, IJsonApiRequest request, + ITargetedFields targetedFields, IAtomicOperationFilter operationFilter) + : JsonApiOperationsController(options, resourceGraph, loggerFactory, processor, request, targetedFields, operationFilter); diff --git a/test/OpenApiTests/Documentation/Skyscraper.cs b/test/OpenApiTests/Documentation/Skyscraper.cs new file mode 100644 index 0000000000..57474ba770 --- /dev/null +++ b/test/OpenApiTests/Documentation/Skyscraper.cs @@ -0,0 +1,33 @@ +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.Documentation; + +/// +/// A tall, continuously habitable building having multiple floors. +/// +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.Documentation")] +public sealed class Skyscraper : Identifiable +{ + /// + /// The height of this building, in meters. + /// + [Attr] + [Required] + public int? HeightInMeters { get; set; } + + /// + /// An optional elevator within this building, providing access to spaces. + /// + [HasOne] + public Elevator? Elevator { get; set; } + + /// + /// The spaces within this building. + /// + [HasMany] + public ISet Spaces { get; set; } = new HashSet(); +} diff --git a/test/OpenApiTests/Documentation/Space.cs b/test/OpenApiTests/Documentation/Space.cs new file mode 100644 index 0000000000..196780dd34 --- /dev/null +++ b/test/OpenApiTests/Documentation/Space.cs @@ -0,0 +1,31 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.Documentation; + +/// +/// A space within a skyscraper, such as an office, hotel, residential space, or retail space. +/// +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.Documentation")] +public sealed class Space : Identifiable +{ + /// + /// The floor number on which this space resides. + /// + [Attr] + public int FloorNumber { get; set; } + + /// + /// The kind of this space. + /// + [Attr] + public SpaceKind Kind { get; set; } + + /// + /// The skyscraper this space exists in. + /// + [HasOne] + public Skyscraper ExistsIn { get; set; } = null!; +} diff --git a/test/OpenApiTests/Documentation/SpaceKind.cs b/test/OpenApiTests/Documentation/SpaceKind.cs new file mode 100644 index 0000000000..a4a3b231b0 --- /dev/null +++ b/test/OpenApiTests/Documentation/SpaceKind.cs @@ -0,0 +1,15 @@ +using JetBrains.Annotations; + +namespace OpenApiTests.Documentation; + +/// +/// Lists the various kinds of spaces within a skyscraper. +/// +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public enum SpaceKind +{ + Office, + Hotel, + Residential, + Retail +} diff --git a/test/OpenApiTests/Headers/Country.cs b/test/OpenApiTests/Headers/Country.cs new file mode 100644 index 0000000000..a0398c03bc --- /dev/null +++ b/test/OpenApiTests/Headers/Country.cs @@ -0,0 +1,19 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.Headers; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.Headers")] +public sealed class Country : Identifiable +{ + [Attr] + public string Name { get; set; } = null!; + + [Attr] + public long Population { get; set; } + + [HasMany] + public ISet Languages { get; set; } = new HashSet(); +} diff --git a/test/OpenApiTests/Headers/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/Headers/GeneratedSwagger/swagger.g.json new file mode 100644 index 0000000000..735ed22d80 --- /dev/null +++ b/test/OpenApiTests/Headers/GeneratedSwagger/swagger.g.json @@ -0,0 +1,2249 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "OpenApiTests", + "version": "1.0" + }, + "servers": [ + { + "url": "http://localhost" + } + ], + "paths": { + "/countries": { + "get": { + "tags": [ + "countries" + ], + "summary": "Retrieves a collection of countries.", + "operationId": "getCountryCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found countries, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/countryCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "countries" + ], + "summary": "Retrieves a collection of countries without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headCountryCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "countries" + ], + "summary": "Creates a new country.", + "operationId": "postCountry", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the country to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createCountryRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The country was successfully created, which resulted in additional changes. The newly created country is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created country can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryCountryResponseDocument" + } + } + } + }, + "204": { + "description": "The country was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/countries/{id}": { + "get": { + "tags": [ + "countries" + ], + "summary": "Retrieves an individual country by its identifier.", + "operationId": "getCountry", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the country to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found country.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryCountryResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The country does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "countries" + ], + "summary": "Retrieves an individual country by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headCountry", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the country to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The country does not exist." + } + } + }, + "patch": { + "tags": [ + "countries" + ], + "summary": "Updates an existing country.", + "operationId": "patchCountry", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the country to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the country to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateCountryRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The country was successfully updated, which resulted in additional changes. The updated country is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryCountryResponseDocument" + } + } + } + }, + "204": { + "description": "The country was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The country or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "countries" + ], + "summary": "Deletes an existing country by its identifier.", + "operationId": "deleteCountry", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the country to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "204": { + "description": "The country was successfully deleted." + }, + "404": { + "description": "The country does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/countries/{id}/languages": { + "get": { + "tags": [ + "countries" + ], + "summary": "Retrieves the related languages of an individual country's languages relationship.", + "operationId": "getCountryLanguages", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the country whose related languages to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found languages, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/languageCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The country does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "countries" + ], + "summary": "Retrieves the related languages of an individual country's languages relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headCountryLanguages", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the country whose related languages to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The country does not exist." + } + } + } + }, + "/countries/{id}/relationships/languages": { + "get": { + "tags": [ + "countries" + ], + "summary": "Retrieves the related language identities of an individual country's languages relationship.", + "operationId": "getCountryLanguagesRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the country whose related language identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found language identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/languageIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The country does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "countries" + ], + "summary": "Retrieves the related language identities of an individual country's languages relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headCountryLanguagesRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the country whose related language identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The country does not exist." + } + } + }, + "post": { + "tags": [ + "countries" + ], + "summary": "Adds existing languages to the languages relationship of an individual country.", + "operationId": "postCountryLanguagesRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the country to add languages to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "description": "The identities of the languages to add to the languages relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyLanguageInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The languages were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The country or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "countries" + ], + "summary": "Assigns existing languages to the languages relationship of an individual country.", + "operationId": "patchCountryLanguagesRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the country whose languages relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "description": "The identities of the languages to assign to the languages relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyLanguageInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The languages relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The country or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "countries" + ], + "summary": "Removes existing languages from the languages relationship of an individual country.", + "operationId": "deleteCountryLanguagesRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the country to remove languages from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "description": "The identities of the languages to remove from the languages relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyLanguageInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The languages were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The country or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "attributesInCountryResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "population": { + "type": "integer", + "format": "int64" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateCountryRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "population": { + "type": "integer", + "format": "int64" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "countries": "#/components/schemas/attributesInCreateCountryRequest" + } + }, + "x-abstract": true + }, + "attributesInLanguageResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "countries": "#/components/schemas/attributesInCountryResponse", + "languages": "#/components/schemas/attributesInLanguageResponse" + } + }, + "x-abstract": true + }, + "attributesInUpdateCountryRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "population": { + "type": "integer", + "format": "int64" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "countries": "#/components/schemas/attributesInUpdateCountryRequest" + } + }, + "x-abstract": true + }, + "countryCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInCountryResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "createCountryRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateCountryRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "dataInCountryResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCountryResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCountryResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateCountryRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateCountryRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateCountryRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInLanguageResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInLanguageResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateCountryRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateCountryRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateCountryRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "errorLinks": { + "type": "object", + "properties": { + "about": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorObject": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorLinks" + } + ], + "nullable": true + }, + "status": { + "type": "string" + }, + "code": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/errorSource" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorResponseDocument": { + "required": [ + "errors", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorTopLevelLinks" + } + ] + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/errorObject" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorSource": { + "type": "object", + "properties": { + "pointer": { + "type": "string", + "nullable": true + }, + "parameter": { + "type": "string", + "nullable": true + }, + "header": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "identifierInRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "languages": "#/components/schemas/languageIdentifierInRequest" + } + }, + "x-abstract": true + }, + "languageCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInLanguageResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "languageIdentifierCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/languageIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "languageIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "languageIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/languageResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "languageResourceType": { + "enum": [ + "languages" + ], + "type": "string" + }, + "meta": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "primaryCountryResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCountryResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "relationshipLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + } + }, + "additionalProperties": false + }, + "relationshipsInCountryResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "type": "object", + "properties": { + "languages": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyLanguageInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateCountryRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "type": "object", + "properties": { + "languages": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyLanguageInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "countries": "#/components/schemas/relationshipsInCreateCountryRequest" + } + }, + "x-abstract": true + }, + "relationshipsInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "countries": "#/components/schemas/relationshipsInCountryResponse" + } + }, + "x-abstract": true + }, + "relationshipsInUpdateCountryRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "languages": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyLanguageInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "countries": "#/components/schemas/relationshipsInUpdateCountryRequest" + } + }, + "x-abstract": true + }, + "resourceCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceIdentifierCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceInCreateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "countries": "#/components/schemas/dataInCreateCountryRequest" + } + }, + "x-abstract": true + }, + "resourceInResponse": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "countries": "#/components/schemas/dataInCountryResponse", + "languages": "#/components/schemas/dataInLanguageResponse" + } + }, + "x-abstract": true + }, + "resourceInUpdateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "countries": "#/components/schemas/dataInUpdateCountryRequest" + } + }, + "x-abstract": true + }, + "resourceLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceType": { + "enum": [ + "countries", + "languages" + ], + "type": "string" + }, + "toManyLanguageInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/languageIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyLanguageInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/languageIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateCountryRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateCountryRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/test/OpenApiTests/Headers/HeaderDbContext.cs b/test/OpenApiTests/Headers/HeaderDbContext.cs new file mode 100644 index 0000000000..02d4bea655 --- /dev/null +++ b/test/OpenApiTests/Headers/HeaderDbContext.cs @@ -0,0 +1,13 @@ +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; +using TestBuildingBlocks; + +namespace OpenApiTests.Headers; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public sealed class HeaderDbContext(DbContextOptions options) + : TestableDbContext(options) +{ + public DbSet Countries => Set(); + public DbSet Languages => Set(); +} diff --git a/test/OpenApiTests/Headers/HeaderFakers.cs b/test/OpenApiTests/Headers/HeaderFakers.cs new file mode 100644 index 0000000000..cb4c50eef3 --- /dev/null +++ b/test/OpenApiTests/Headers/HeaderFakers.cs @@ -0,0 +1,36 @@ +using System.Globalization; +using Bogus; +using JetBrains.Annotations; +using TestBuildingBlocks; + +// @formatter:wrap_chained_method_calls chop_if_long +// @formatter:wrap_before_first_method_call true + +namespace OpenApiTests.Headers; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public sealed class HeaderFakers +{ + private static readonly Lazy LazyLanguageNames = new(() => CultureInfo + .GetCultures(CultureTypes.NeutralCultures) + .Select(culture => culture.DisplayName) + .ToArray()); + + private static readonly Lazy LazyLanguageCodes = new(() => CultureInfo + .GetCultures(CultureTypes.NeutralCultures) + .Select(culture => culture.ThreeLetterISOLanguageName) + .ToArray()); + + private readonly Lazy> _lazyCountryFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(country => country.Name, faker => faker.Address.Country()) + .RuleFor(country => country.Population, faker => faker.Random.Long(0, 2_000_000_000))); + + private readonly Lazy> _lazyLanguageFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(language => language.Name, faker => faker.PickRandom(LazyLanguageNames.Value)) + .RuleFor(language => language.Code, faker => faker.PickRandom(LazyLanguageCodes.Value))); + + public Faker Country => _lazyCountryFaker.Value; + public Faker Language => _lazyLanguageFaker.Value; +} diff --git a/test/OpenApiTests/Headers/HeaderTests.cs b/test/OpenApiTests/Headers/HeaderTests.cs new file mode 100644 index 0000000000..4e363b2c89 --- /dev/null +++ b/test/OpenApiTests/Headers/HeaderTests.cs @@ -0,0 +1,147 @@ +using System.Text.Json; +using FluentAssertions; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.Headers; + +public sealed class HeaderTests : IClassFixture, HeaderDbContext>> +{ + private readonly OpenApiTestContext, HeaderDbContext> _testContext; + + public HeaderTests(OpenApiTestContext, HeaderDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + + testContext.UseController(); + + testContext.SetTestOutputHelper(testOutputHelper); + testContext.SwaggerDocumentOutputDirectory = $"{GetType().Namespace!.Replace('.', '/')}/GeneratedSwagger"; + } + + [Theory] + [InlineData("/countries.get")] + [InlineData("/countries.head")] + [InlineData("/countries/{id}.get")] + [InlineData("/countries/{id}.head")] + [InlineData("/countries/{id}/languages.get")] + [InlineData("/countries/{id}/languages.head")] + [InlineData("/countries/{id}/relationships/languages.get")] + [InlineData("/countries/{id}/relationships/languages.head")] + public async Task Endpoints_have_caching_headers(string endpointPath) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath($"paths.{endpointPath}.parameters").With(parametersElement => + { + parametersElement.EnumerateArray().Should().ContainSingle(parameterElement => parameterElement.GetProperty("in").ValueEquals("header")).Subject + .With(parameterElement => + { + parameterElement.Should().HaveProperty("name", "If-None-Match"); + parameterElement.Should().NotContainPath("required"); + + parameterElement.Should().HaveProperty("description", + "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint."); + + parameterElement.Should().ContainPath("schema").With(schemaElement => + { + schemaElement.Should().HaveProperty("type", "string"); + }); + }); + }); + + document.Should().ContainPath($"paths.{endpointPath}.responses.200.headers.ETag").With(AssertETag); + document.Should().ContainPath($"paths.{endpointPath}.responses.304.headers.ETag").With(AssertETag); + + return; + + static void AssertETag(JsonElement etagElement) + { + etagElement.Should().HaveProperty("description", + "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes."); + + etagElement.Should().HaveProperty("required", true); + + etagElement.Should().ContainPath("schema").With(schemaElement => + { + schemaElement.Should().HaveProperty("type", "string"); + }); + } + } + + [Theory] + [InlineData("/countries.post")] + [InlineData("/countries/{id}.patch")] + [InlineData("/countries/{id}.delete")] + [InlineData("/countries/{id}/relationships/languages.post")] + [InlineData("/countries/{id}/relationships/languages.patch")] + [InlineData("/countries/{id}/relationships/languages.delete")] + public async Task Endpoints_do_not_have_caching_headers(string endpointPath) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath($"paths.{endpointPath}.parameters").With(parametersElement => + { + parametersElement.EnumerateArray().Should().NotContain(parameterElement => parameterElement.GetProperty("name").ValueEquals("If-None-Match")); + }); + + document.Should().ContainPath($"paths.{endpointPath}.responses").With(responsesElement => + { + foreach (JsonProperty responseProperty in responsesElement.EnumerateObject()) + { + responseProperty.Value.Should().NotContainPath("headers.ETag"); + } + }); + } + + [Theory] + [InlineData("/countries.head")] + [InlineData("/countries/{id}.head")] + [InlineData("/countries/{id}/languages.head")] + [InlineData("/countries/{id}/relationships/languages.head")] + public async Task Endpoints_have_content_length_response_header(string endpointPath) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath($"paths.{endpointPath}.responses.200.headers.Content-Length").With(contentLengthElement => + { + contentLengthElement.Should().HaveProperty("description", "Size of the HTTP response body, in bytes."); + + contentLengthElement.Should().HaveProperty("required", true); + + contentLengthElement.Should().ContainPath("schema").With(schemaElement => + { + schemaElement.Should().HaveProperty("type", "integer"); + schemaElement.Should().HaveProperty("format", "int64"); + }); + }); + } + + [Fact] + public async Task Post_resource_endpoint_has_location_response_header() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./countries.post.responses.201.headers.Location").With(locationElement => + { + locationElement.Should().HaveProperty("description", "The URL at which the newly created country can be retrieved."); + + locationElement.Should().HaveProperty("required", true); + + locationElement.Should().ContainPath("schema").With(schemaElement => + { + schemaElement.Should().HaveProperty("type", "string"); + schemaElement.Should().HaveProperty("format", "uri"); + }); + }); + } +} diff --git a/test/OpenApiTests/Headers/Language.cs b/test/OpenApiTests/Headers/Language.cs new file mode 100644 index 0000000000..3f2eae5ff3 --- /dev/null +++ b/test/OpenApiTests/Headers/Language.cs @@ -0,0 +1,16 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.Headers; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.Headers")] +public sealed class Language : Identifiable +{ + [Attr] + public string Code { get; set; } = null!; + + [Attr] + public string Name { get; set; } = null!; +} diff --git a/test/OpenApiTests/JsonPathBuilder.cs b/test/OpenApiTests/JsonPathBuilder.cs new file mode 100644 index 0000000000..b3c16e4a65 --- /dev/null +++ b/test/OpenApiTests/JsonPathBuilder.cs @@ -0,0 +1,76 @@ +using System.Collections.ObjectModel; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Resources.Annotations; + +#pragma warning disable AV1008 // Class should not be static + +namespace OpenApiTests; + +internal static class JsonPathBuilder +{ + public static readonly IReadOnlyCollection KnownEndpoints = + [ + JsonApiEndpoints.GetCollection, + JsonApiEndpoints.GetSingle, + JsonApiEndpoints.GetSecondary, + JsonApiEndpoints.GetRelationship, + JsonApiEndpoints.Post, + JsonApiEndpoints.PostRelationship, + JsonApiEndpoints.Patch, + JsonApiEndpoints.PatchRelationship, + JsonApiEndpoints.Delete, + JsonApiEndpoints.DeleteRelationship + ]; + + public static IReadOnlyDictionary> GetEndpointPaths(ResourceType resourceType) + { + var endpointToPathMap = new Dictionary> + { + [JsonApiEndpoints.GetCollection] = + [ + $"paths./{resourceType.PublicName}.get", + $"paths./{resourceType.PublicName}.head" + ], + [JsonApiEndpoints.GetSingle] = + [ + $"paths./{resourceType.PublicName}/{{id}}.get", + $"paths./{resourceType.PublicName}/{{id}}.head" + ], + [JsonApiEndpoints.GetSecondary] = [], + [JsonApiEndpoints.GetRelationship] = [], + [JsonApiEndpoints.Post] = [$"paths./{resourceType.PublicName}.post"], + [JsonApiEndpoints.PostRelationship] = [], + [JsonApiEndpoints.Patch] = [$"paths./{resourceType.PublicName}/{{id}}.patch"], + [JsonApiEndpoints.PatchRelationship] = [], + [JsonApiEndpoints.Delete] = [$"paths./{resourceType.PublicName}/{{id}}.delete"], + [JsonApiEndpoints.DeleteRelationship] = [] + }; + + foreach (RelationshipAttribute relationship in resourceType.Relationships) + { + endpointToPathMap[JsonApiEndpoints.GetSecondary].AddRange([ + $"paths./{resourceType.PublicName}/{{id}}/{relationship.PublicName}.get", + $"paths./{resourceType.PublicName}/{{id}}/{relationship.PublicName}.head" + ]); + + endpointToPathMap[JsonApiEndpoints.GetRelationship].AddRange([ + $"paths./{resourceType.PublicName}/{{id}}/relationships/{relationship.PublicName}.get", + $"paths./{resourceType.PublicName}/{{id}}/relationships/{relationship.PublicName}.head" + ]); + + endpointToPathMap[JsonApiEndpoints.PatchRelationship].Add($"paths./{resourceType.PublicName}/{{id}}/relationships/{relationship.PublicName}.patch"); + + if (relationship is HasManyAttribute) + { + endpointToPathMap[JsonApiEndpoints.PostRelationship].Add( + $"paths./{resourceType.PublicName}/{{id}}/relationships/{relationship.PublicName}.post"); + + endpointToPathMap[JsonApiEndpoints.DeleteRelationship].Add( + $"paths./{resourceType.PublicName}/{{id}}/relationships/{relationship.PublicName}.delete"); + } + } + + return endpointToPathMap.ToDictionary(pair => pair.Key, pair => pair.Value.AsReadOnly()).AsReadOnly(); + } +} diff --git a/test/OpenApiTests/LegacyOpenApi/AircraftKind.cs b/test/OpenApiTests/LegacyOpenApi/AircraftKind.cs new file mode 100644 index 0000000000..0b0ceb63e5 --- /dev/null +++ b/test/OpenApiTests/LegacyOpenApi/AircraftKind.cs @@ -0,0 +1,12 @@ +using JetBrains.Annotations; + +namespace OpenApiTests.LegacyOpenApi; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public enum AircraftKind +{ + Turboprops, + LightJet, + MidSizeJet, + JumboJet +} diff --git a/test/OpenApiTests/LegacyOpenApi/Airline.cs b/test/OpenApiTests/LegacyOpenApi/Airline.cs new file mode 100644 index 0000000000..8a49eee69b --- /dev/null +++ b/test/OpenApiTests/LegacyOpenApi/Airline.cs @@ -0,0 +1,14 @@ +using JetBrains.Annotations; + +namespace OpenApiTests.LegacyOpenApi; + +/// +/// Lists the various airlines used in this API. +/// +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public enum Airline : byte +{ + DeltaAirLines, + LufthansaGroup, + AirFranceKlm +} diff --git a/test/OpenApiTests/LegacyOpenApi/Airplane.cs b/test/OpenApiTests/LegacyOpenApi/Airplane.cs new file mode 100644 index 0000000000..aa89d99f61 --- /dev/null +++ b/test/OpenApiTests/LegacyOpenApi/Airplane.cs @@ -0,0 +1,44 @@ +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.LegacyOpenApi; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.LegacyOpenApi")] +public sealed class Airplane : Identifiable +{ + [Attr(Capabilities = AttrCapabilities.AllowView | AttrCapabilities.AllowCreate | AttrCapabilities.AllowChange)] + [MaxLength(255)] + public string Name { get; set; } = null!; + + [Attr(Capabilities = AttrCapabilities.AllowView | AttrCapabilities.AllowCreate | AttrCapabilities.AllowChange)] + [MaxLength(16)] + public string? SerialNumber { get; set; } + + [Attr(Capabilities = AttrCapabilities.AllowView | AttrCapabilities.AllowCreate | AttrCapabilities.AllowChange)] + public int? AirtimeInHours { get; set; } + + [Attr(Capabilities = AttrCapabilities.AllowView | AttrCapabilities.AllowCreate | AttrCapabilities.AllowChange)] + public DateTime? LastServicedAt { get; set; } + + /// + /// Gets the day on which this airplane was manufactured. + /// + [Attr] + public DateTime ManufacturedAt { get; set; } + + [Attr(Capabilities = AttrCapabilities.AllowView | AttrCapabilities.AllowChange)] + public bool IsInMaintenance { get; set; } + + [Attr(Capabilities = AttrCapabilities.AllowView | AttrCapabilities.AllowChange)] + [MaxLength(85)] + public string? ManufacturedInCity { get; set; } + + [Attr(Capabilities = AttrCapabilities.AllowView)] + public AircraftKind Kind { get; set; } + + [HasMany] + public ISet Flights { get; set; } = new HashSet(); +} diff --git a/test/OpenApiTests/LegacyOpenApi/CabinArea.cs b/test/OpenApiTests/LegacyOpenApi/CabinArea.cs new file mode 100644 index 0000000000..e9c3ec151a --- /dev/null +++ b/test/OpenApiTests/LegacyOpenApi/CabinArea.cs @@ -0,0 +1,11 @@ +using JetBrains.Annotations; + +namespace OpenApiTests.LegacyOpenApi; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public enum CabinArea +{ + FirstClass, + BusinessClass, + EconomyClass +} diff --git a/test/OpenApiTests/LegacyOpenApi/Flight.cs b/test/OpenApiTests/LegacyOpenApi/Flight.cs new file mode 100644 index 0000000000..5baa315523 --- /dev/null +++ b/test/OpenApiTests/LegacyOpenApi/Flight.cs @@ -0,0 +1,45 @@ +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.LegacyOpenApi; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.LegacyOpenApi")] +public sealed class Flight : Identifiable +{ + [Attr(Capabilities = AttrCapabilities.AllowView | AttrCapabilities.AllowChange)] + [MaxLength(40)] + public string FinalDestination { get; set; } = null!; + + [Attr(Capabilities = AttrCapabilities.AllowView | AttrCapabilities.AllowChange)] + [MaxLength(2000)] + public string? StopOverDestination { get; set; } + + [Attr(PublicName = "operated-by", Capabilities = AttrCapabilities.AllowView | AttrCapabilities.AllowChange)] + public Airline Airline { get; set; } + + [Attr] + public DateTime? DepartsAt { get; set; } + + [Attr] + public DateTime? ArrivesAt { get; set; } + + [HasMany] + public ISet CabinCrewMembers { get; set; } = new HashSet(); + + [HasOne] + public FlightAttendant Purser { get; set; } = null!; + + [HasOne] + public FlightAttendant? BackupPurser { get; set; } + + [Attr] + [NotMapped] + public ICollection ServicesOnBoard { get; set; } = new HashSet(); + + [HasMany] + public ICollection Passengers { get; set; } = new HashSet(); +} diff --git a/test/OpenApiTests/LegacyOpenApi/FlightAttendant.cs b/test/OpenApiTests/LegacyOpenApi/FlightAttendant.cs new file mode 100644 index 0000000000..6eb6872072 --- /dev/null +++ b/test/OpenApiTests/LegacyOpenApi/FlightAttendant.cs @@ -0,0 +1,39 @@ +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.LegacyOpenApi; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.LegacyOpenApi")] +public sealed class FlightAttendant : Identifiable +{ + [Attr(Capabilities = AttrCapabilities.AllowView | AttrCapabilities.AllowFilter)] + public override string Id { get; set; } = null!; + + [Attr(Capabilities = AttrCapabilities.None)] + public FlightAttendantExpertiseLevel ExpertiseLevel { get; set; } + + [Attr(Capabilities = AttrCapabilities.All)] + [Required] + [EmailAddress] + public string? EmailAddress { get; set; } + + [Attr(Capabilities = AttrCapabilities.All)] + [Range(18, 75)] + public int Age { get; set; } + + [Attr(Capabilities = AttrCapabilities.AllowView | AttrCapabilities.AllowCreate)] + [Url] + public string ProfileImageUrl { get; set; } = null!; + + [Attr] + public long DistanceTraveledInKilometers { get; set; } + + [HasMany] + public ISet ScheduledForFlights { get; set; } = new HashSet(); + + [HasMany] + public ISet PurserOnFlights { get; set; } = new HashSet(); +} diff --git a/test/OpenApiTests/LegacyOpenApi/FlightAttendantExpertiseLevel.cs b/test/OpenApiTests/LegacyOpenApi/FlightAttendantExpertiseLevel.cs new file mode 100644 index 0000000000..cb5f276014 --- /dev/null +++ b/test/OpenApiTests/LegacyOpenApi/FlightAttendantExpertiseLevel.cs @@ -0,0 +1,12 @@ +using JetBrains.Annotations; + +namespace OpenApiTests.LegacyOpenApi; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public enum FlightAttendantExpertiseLevel +{ + Junior, + Intermediate, + Senior, + Purser +} diff --git a/test/OpenApiTests/LegacyOpenApi/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/LegacyOpenApi/GeneratedSwagger/swagger.g.json new file mode 100644 index 0000000000..f72814347b --- /dev/null +++ b/test/OpenApiTests/LegacyOpenApi/GeneratedSwagger/swagger.g.json @@ -0,0 +1,8858 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "OpenApiTests", + "version": "1.0" + }, + "servers": [ + { + "url": "http://localhost" + } + ], + "paths": { + "/api/airplanes": { + "get": { + "tags": [ + "airplanes" + ], + "summary": "Retrieves a collection of airplanes.", + "operationId": "get-airplane-collection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found airplanes, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/airplane-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "airplanes" + ], + "summary": "Retrieves a collection of airplanes without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-airplane-collection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "airplanes" + ], + "summary": "Creates a new airplane.", + "operationId": "post-airplane", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the airplane to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/create-airplane-request-document" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The airplane was successfully created, which resulted in additional changes. The newly created airplane is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created airplane can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-airplane-response-document" + } + } + } + }, + "204": { + "description": "The airplane was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/airplanes/{id}": { + "get": { + "tags": [ + "airplanes" + ], + "summary": "Retrieves an individual airplane by its identifier.", + "operationId": "get-airplane", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the airplane to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found airplane.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-airplane-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The airplane does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "airplanes" + ], + "summary": "Retrieves an individual airplane by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-airplane", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the airplane to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The airplane does not exist." + } + } + }, + "patch": { + "tags": [ + "airplanes" + ], + "summary": "Updates an existing airplane.", + "operationId": "patch-airplane", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the airplane to update.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the airplane to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/update-airplane-request-document" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The airplane was successfully updated, which resulted in additional changes. The updated airplane is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-airplane-response-document" + } + } + } + }, + "204": { + "description": "The airplane was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The airplane or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "delete": { + "tags": [ + "airplanes" + ], + "summary": "Deletes an existing airplane by its identifier.", + "operationId": "delete-airplane", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the airplane to delete.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "The airplane was successfully deleted." + }, + "404": { + "description": "The airplane does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/airplanes/{id}/flights": { + "get": { + "tags": [ + "airplanes" + ], + "summary": "Retrieves the related flights of an individual airplane's flights relationship.", + "operationId": "get-airplane-flights", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the airplane whose related flights to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flights, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/flight-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The airplane does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "airplanes" + ], + "summary": "Retrieves the related flights of an individual airplane's flights relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-airplane-flights", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the airplane whose related flights to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The airplane does not exist." + } + } + } + }, + "/api/airplanes/{id}/relationships/flights": { + "get": { + "tags": [ + "airplanes" + ], + "summary": "Retrieves the related flight identities of an individual airplane's flights relationship.", + "operationId": "get-airplane-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the airplane whose related flight identities to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/flight-identifier-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The airplane does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "airplanes" + ], + "summary": "Retrieves the related flight identities of an individual airplane's flights relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-airplane-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the airplane whose related flight identities to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The airplane does not exist." + } + } + }, + "post": { + "tags": [ + "airplanes" + ], + "summary": "Adds existing flights to the flights relationship of an individual airplane.", + "operationId": "post-airplane-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the airplane to add flights to.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flights to add to the flights relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The flights were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The airplane or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "patch": { + "tags": [ + "airplanes" + ], + "summary": "Assigns existing flights to the flights relationship of an individual airplane.", + "operationId": "patch-airplane-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the airplane whose flights relationship to assign.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flights to assign to the flights relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The flights relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The airplane or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "delete": { + "tags": [ + "airplanes" + ], + "summary": "Removes existing flights from the flights relationship of an individual airplane.", + "operationId": "delete-airplane-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the airplane to remove flights from.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flights to remove from the flights relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The flights were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The airplane or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/flight-attendants": { + "get": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves a collection of flight-attendants.", + "operationId": "get-flight-attendant-collection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight-attendants, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/flight-attendant-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves a collection of flight-attendants without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-attendant-collection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "flight-attendants" + ], + "summary": "Creates a new flight-attendant.", + "operationId": "post-flight-attendant", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the flight-attendant to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/create-flight-attendant-request-document" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The flight-attendant was successfully created, which resulted in additional changes. The newly created flight-attendant is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created flight-attendant can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-flight-attendant-response-document" + } + } + } + }, + "204": { + "description": "The flight-attendant was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/flight-attendants/{id}": { + "get": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves an individual flight-attendant by its identifier.", + "operationId": "get-flight-attendant", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight-attendant.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-flight-attendant-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves an individual flight-attendant by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-attendant", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight-attendant does not exist." + } + } + }, + "patch": { + "tags": [ + "flight-attendants" + ], + "summary": "Updates an existing flight-attendant.", + "operationId": "patch-flight-attendant", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant to update.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the flight-attendant to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/update-flight-attendant-request-document" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The flight-attendant was successfully updated, which resulted in additional changes. The updated flight-attendant is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-flight-attendant-response-document" + } + } + } + }, + "204": { + "description": "The flight-attendant was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "delete": { + "tags": [ + "flight-attendants" + ], + "summary": "Deletes an existing flight-attendant by its identifier.", + "operationId": "delete-flight-attendant", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant to delete.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "The flight-attendant was successfully deleted." + }, + "404": { + "description": "The flight-attendant does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/flight-attendants/{id}/purser-on-flights": { + "get": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves the related flights of an individual flight-attendant's purser-on-flights relationship.", + "operationId": "get-flight-attendant-purser-on-flights", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant whose related flights to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flights, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/flight-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves the related flights of an individual flight-attendant's purser-on-flights relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-attendant-purser-on-flights", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant whose related flights to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight-attendant does not exist." + } + } + } + }, + "/api/flight-attendants/{id}/relationships/purser-on-flights": { + "get": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves the related flight identities of an individual flight-attendant's purser-on-flights relationship.", + "operationId": "get-flight-attendant-purser-on-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant whose related flight identities to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/flight-identifier-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves the related flight identities of an individual flight-attendant's purser-on-flights relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-attendant-purser-on-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant whose related flight identities to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight-attendant does not exist." + } + } + }, + "post": { + "tags": [ + "flight-attendants" + ], + "summary": "Adds existing flights to the purser-on-flights relationship of an individual flight-attendant.", + "operationId": "post-flight-attendant-purser-on-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant to add flights to.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flights to add to the purser-on-flights relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The flights were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "patch": { + "tags": [ + "flight-attendants" + ], + "summary": "Assigns existing flights to the purser-on-flights relationship of an individual flight-attendant.", + "operationId": "patch-flight-attendant-purser-on-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant whose purser-on-flights relationship to assign.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flights to assign to the purser-on-flights relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The purser-on-flights relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "delete": { + "tags": [ + "flight-attendants" + ], + "summary": "Removes existing flights from the purser-on-flights relationship of an individual flight-attendant.", + "operationId": "delete-flight-attendant-purser-on-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant to remove flights from.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flights to remove from the purser-on-flights relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The flights were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/flight-attendants/{id}/scheduled-for-flights": { + "get": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves the related flights of an individual flight-attendant's scheduled-for-flights relationship.", + "operationId": "get-flight-attendant-scheduled-for-flights", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant whose related flights to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flights, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/flight-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves the related flights of an individual flight-attendant's scheduled-for-flights relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-attendant-scheduled-for-flights", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant whose related flights to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight-attendant does not exist." + } + } + } + }, + "/api/flight-attendants/{id}/relationships/scheduled-for-flights": { + "get": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves the related flight identities of an individual flight-attendant's scheduled-for-flights relationship.", + "operationId": "get-flight-attendant-scheduled-for-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant whose related flight identities to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/flight-identifier-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves the related flight identities of an individual flight-attendant's scheduled-for-flights relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-attendant-scheduled-for-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant whose related flight identities to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight-attendant does not exist." + } + } + }, + "post": { + "tags": [ + "flight-attendants" + ], + "summary": "Adds existing flights to the scheduled-for-flights relationship of an individual flight-attendant.", + "operationId": "post-flight-attendant-scheduled-for-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant to add flights to.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flights to add to the scheduled-for-flights relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The flights were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "patch": { + "tags": [ + "flight-attendants" + ], + "summary": "Assigns existing flights to the scheduled-for-flights relationship of an individual flight-attendant.", + "operationId": "patch-flight-attendant-scheduled-for-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant whose scheduled-for-flights relationship to assign.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flights to assign to the scheduled-for-flights relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The scheduled-for-flights relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "delete": { + "tags": [ + "flight-attendants" + ], + "summary": "Removes existing flights from the scheduled-for-flights relationship of an individual flight-attendant.", + "operationId": "delete-flight-attendant-scheduled-for-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant to remove flights from.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flights to remove from the scheduled-for-flights relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The flights were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/flights": { + "get": { + "tags": [ + "flights" + ], + "summary": "Retrieves a collection of flights.", + "operationId": "get-flight-collection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flights, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/flight-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flights" + ], + "summary": "Retrieves a collection of flights without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-collection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "flights" + ], + "summary": "Creates a new flight.", + "operationId": "post-flight", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the flight to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/create-flight-request-document" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The flight was successfully created, which resulted in additional changes. The newly created flight is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created flight can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-flight-response-document" + } + } + } + }, + "204": { + "description": "The flight was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/flights/{id}": { + "get": { + "tags": [ + "flights" + ], + "summary": "Retrieves an individual flight by its identifier.", + "operationId": "get-flight", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-flight-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flights" + ], + "summary": "Retrieves an individual flight by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight does not exist." + } + } + }, + "patch": { + "tags": [ + "flights" + ], + "summary": "Updates an existing flight.", + "operationId": "patch-flight", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight to update.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the flight to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/update-flight-request-document" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The flight was successfully updated, which resulted in additional changes. The updated flight is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-flight-response-document" + } + } + } + }, + "204": { + "description": "The flight was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "delete": { + "tags": [ + "flights" + ], + "summary": "Deletes an existing flight by its identifier.", + "operationId": "delete-flight", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight to delete.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "The flight was successfully deleted." + }, + "404": { + "description": "The flight does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/flights/{id}/backup-purser": { + "get": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendant of an individual flight's backup-purser relationship.", + "operationId": "get-flight-backup-purser", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendant to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight-attendant, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullable-secondary-flight-attendant-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendant of an individual flight's backup-purser relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-backup-purser", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendant to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight does not exist." + } + } + } + }, + "/api/flights/{id}/relationships/backup-purser": { + "get": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendant identity of an individual flight's backup-purser relationship.", + "operationId": "get-flight-backup-purser-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendant identity to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight-attendant identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullable-flight-attendant-identifier-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendant identity of an individual flight's backup-purser relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-backup-purser-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendant identity to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight does not exist." + } + } + }, + "patch": { + "tags": [ + "flights" + ], + "summary": "Clears or assigns an existing flight-attendant to the backup-purser relationship of an individual flight.", + "operationId": "patch-flight-backup-purser-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose backup-purser relationship to assign or clear.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identity of the flight-attendant to assign to the backup-purser relationship, or `null` to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/nullable-to-one-flight-attendant-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The backup-purser relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/flights/{id}/cabin-crew-members": { + "get": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendants of an individual flight's cabin-crew-members relationship.", + "operationId": "get-flight-cabin-crew-members", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendants to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight-attendants, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/flight-attendant-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendants of an individual flight's cabin-crew-members relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-cabin-crew-members", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendants to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight does not exist." + } + } + } + }, + "/api/flights/{id}/relationships/cabin-crew-members": { + "get": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendant identities of an individual flight's cabin-crew-members relationship.", + "operationId": "get-flight-cabin-crew-members-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendant identities to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight-attendant identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/flight-attendant-identifier-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendant identities of an individual flight's cabin-crew-members relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-cabin-crew-members-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendant identities to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight does not exist." + } + } + }, + "post": { + "tags": [ + "flights" + ], + "summary": "Adds existing flight-attendants to the cabin-crew-members relationship of an individual flight.", + "operationId": "post-flight-cabin-crew-members-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight to add flight-attendants to.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flight-attendants to add to the cabin-crew-members relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-attendant-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The flight-attendants were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "patch": { + "tags": [ + "flights" + ], + "summary": "Assigns existing flight-attendants to the cabin-crew-members relationship of an individual flight.", + "operationId": "patch-flight-cabin-crew-members-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose cabin-crew-members relationship to assign.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flight-attendants to assign to the cabin-crew-members relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-attendant-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The cabin-crew-members relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "delete": { + "tags": [ + "flights" + ], + "summary": "Removes existing flight-attendants from the cabin-crew-members relationship of an individual flight.", + "operationId": "delete-flight-cabin-crew-members-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight to remove flight-attendants from.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flight-attendants to remove from the cabin-crew-members relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-attendant-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The flight-attendants were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/flights/{id}/passengers": { + "get": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related passengers of an individual flight's passengers relationship.", + "operationId": "get-flight-passengers", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related passengers to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found passengers, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/passenger-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related passengers of an individual flight's passengers relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-passengers", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related passengers to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight does not exist." + } + } + } + }, + "/api/flights/{id}/relationships/passengers": { + "get": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related passenger identities of an individual flight's passengers relationship.", + "operationId": "get-flight-passengers-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related passenger identities to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found passenger identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/passenger-identifier-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related passenger identities of an individual flight's passengers relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-passengers-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related passenger identities to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight does not exist." + } + } + }, + "post": { + "tags": [ + "flights" + ], + "summary": "Adds existing passengers to the passengers relationship of an individual flight.", + "operationId": "post-flight-passengers-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight to add passengers to.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the passengers to add to the passengers relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-passenger-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The passengers were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "patch": { + "tags": [ + "flights" + ], + "summary": "Assigns existing passengers to the passengers relationship of an individual flight.", + "operationId": "patch-flight-passengers-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose passengers relationship to assign.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the passengers to assign to the passengers relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-passenger-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The passengers relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "delete": { + "tags": [ + "flights" + ], + "summary": "Removes existing passengers from the passengers relationship of an individual flight.", + "operationId": "delete-flight-passengers-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight to remove passengers from.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the passengers to remove from the passengers relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-passenger-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The passengers were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/flights/{id}/purser": { + "get": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendant of an individual flight's purser relationship.", + "operationId": "get-flight-purser", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendant to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight-attendant, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/secondary-flight-attendant-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendant of an individual flight's purser relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-purser", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendant to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight does not exist." + } + } + } + }, + "/api/flights/{id}/relationships/purser": { + "get": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendant identity of an individual flight's purser relationship.", + "operationId": "get-flight-purser-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendant identity to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight-attendant identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/flight-attendant-identifier-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendant identity of an individual flight's purser relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-purser-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendant identity to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight does not exist." + } + } + }, + "patch": { + "tags": [ + "flights" + ], + "summary": "Assigns an existing flight-attendant to the purser relationship of an individual flight.", + "operationId": "patch-flight-purser-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose purser relationship to assign.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identity of the flight-attendant to assign to the purser relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-one-flight-attendant-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The purser relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/passengers": { + "get": { + "tags": [ + "passengers" + ], + "summary": "Retrieves a collection of passengers.", + "operationId": "get-passenger-collection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found passengers, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/passenger-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "passengers" + ], + "summary": "Retrieves a collection of passengers without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-passenger-collection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "passengers" + ], + "summary": "Creates a new passenger.", + "operationId": "post-passenger", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the passenger to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/create-passenger-request-document" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The passenger was successfully created, which resulted in additional changes. The newly created passenger is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created passenger can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-passenger-response-document" + } + } + } + }, + "204": { + "description": "The passenger was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/passengers/{id}": { + "get": { + "tags": [ + "passengers" + ], + "summary": "Retrieves an individual passenger by its identifier.", + "operationId": "get-passenger", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the passenger to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found passenger.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-passenger-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The passenger does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "passengers" + ], + "summary": "Retrieves an individual passenger by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-passenger", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the passenger to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The passenger does not exist." + } + } + }, + "patch": { + "tags": [ + "passengers" + ], + "summary": "Updates an existing passenger.", + "operationId": "patch-passenger", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the passenger to update.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the passenger to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/update-passenger-request-document" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The passenger was successfully updated, which resulted in additional changes. The updated passenger is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-passenger-response-document" + } + } + } + }, + "204": { + "description": "The passenger was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The passenger or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "delete": { + "tags": [ + "passengers" + ], + "summary": "Deletes an existing passenger by its identifier.", + "operationId": "delete-passenger", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the passenger to delete.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "The passenger was successfully deleted." + }, + "404": { + "description": "The passenger does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "aircraft-kind": { + "enum": [ + "Turboprops", + "LightJet", + "MidSizeJet", + "JumboJet" + ], + "type": "string" + }, + "airline": { + "enum": [ + "DeltaAirLines", + "LufthansaGroup", + "AirFranceKlm" + ], + "type": "string", + "description": "Lists the various airlines used in this API." + }, + "airplane-collection-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-collection-top-level-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/data-in-airplane-response" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "attributes-in-airplane-response": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-response" + }, + { + "type": "object", + "properties": { + "name": { + "maxLength": 255, + "type": "string" + }, + "serial-number": { + "maxLength": 16, + "type": "string", + "nullable": true + }, + "airtime-in-hours": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "last-serviced-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "manufactured-at": { + "type": "string", + "description": "Gets the day on which this airplane was manufactured.", + "format": "date-time" + }, + "is-in-maintenance": { + "type": "boolean" + }, + "manufactured-in-city": { + "maxLength": 85, + "type": "string", + "nullable": true + }, + "kind": { + "allOf": [ + { + "$ref": "#/components/schemas/aircraft-kind" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-create-airplane-request": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-create-request" + }, + { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "maxLength": 255, + "type": "string" + }, + "serial-number": { + "maxLength": 16, + "type": "string", + "nullable": true + }, + "airtime-in-hours": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "last-serviced-at": { + "type": "string", + "format": "date-time", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-create-flight-attendant-request": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-create-request" + }, + { + "required": [ + "email-address", + "profile-image-url" + ], + "type": "object", + "properties": { + "email-address": { + "minLength": 1, + "type": "string", + "format": "email" + }, + "age": { + "maximum": 75, + "minimum": 18, + "type": "integer", + "format": "int32" + }, + "profile-image-url": { + "type": "string", + "format": "uri" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-create-passenger-request": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-create-request" + }, + { + "required": [ + "document-number" + ], + "type": "object", + "properties": { + "document-number": { + "maxLength": 9, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-create-request": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "airplanes": "#/components/schemas/attributes-in-create-airplane-request", + "flight-attendants": "#/components/schemas/attributes-in-create-flight-attendant-request", + "passengers": "#/components/schemas/attributes-in-create-passenger-request" + } + }, + "x-abstract": true + }, + "attributes-in-flight-attendant-response": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-response" + }, + { + "type": "object", + "properties": { + "email-address": { + "minLength": 1, + "type": "string", + "format": "email" + }, + "age": { + "maximum": 75, + "minimum": 18, + "type": "integer", + "format": "int32" + }, + "profile-image-url": { + "type": "string", + "format": "uri" + }, + "distance-traveled-in-kilometers": { + "type": "integer", + "format": "int64" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-flight-response": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-response" + }, + { + "type": "object", + "properties": { + "final-destination": { + "maxLength": 40, + "type": "string" + }, + "stop-over-destination": { + "maxLength": 2000, + "type": "string", + "nullable": true + }, + "operated-by": { + "allOf": [ + { + "$ref": "#/components/schemas/airline" + } + ] + }, + "departs-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "arrives-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "services-on-board": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-passenger-response": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-response" + }, + { + "type": "object", + "properties": { + "full-name": { + "type": "string", + "nullable": true + }, + "cabin-area": { + "allOf": [ + { + "$ref": "#/components/schemas/cabin-area" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-response": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "airplanes": "#/components/schemas/attributes-in-airplane-response", + "flight-attendants": "#/components/schemas/attributes-in-flight-attendant-response", + "flights": "#/components/schemas/attributes-in-flight-response", + "passengers": "#/components/schemas/attributes-in-passenger-response" + } + }, + "x-abstract": true + }, + "attributes-in-update-airplane-request": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-update-request" + }, + { + "type": "object", + "properties": { + "name": { + "maxLength": 255, + "type": "string" + }, + "serial-number": { + "maxLength": 16, + "type": "string", + "nullable": true + }, + "airtime-in-hours": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "last-serviced-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "is-in-maintenance": { + "type": "boolean" + }, + "manufactured-in-city": { + "maxLength": 85, + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-update-flight-attendant-request": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-update-request" + }, + { + "type": "object", + "properties": { + "email-address": { + "minLength": 1, + "type": "string", + "format": "email" + }, + "age": { + "maximum": 75, + "minimum": 18, + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-update-flight-request": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-update-request" + }, + { + "type": "object", + "properties": { + "final-destination": { + "maxLength": 40, + "type": "string" + }, + "stop-over-destination": { + "maxLength": 2000, + "type": "string", + "nullable": true + }, + "operated-by": { + "allOf": [ + { + "$ref": "#/components/schemas/airline" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-update-passenger-request": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-update-request" + }, + { + "type": "object", + "properties": { + "document-number": { + "maxLength": 9, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-update-request": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "airplanes": "#/components/schemas/attributes-in-update-airplane-request", + "flight-attendants": "#/components/schemas/attributes-in-update-flight-attendant-request", + "flights": "#/components/schemas/attributes-in-update-flight-request", + "passengers": "#/components/schemas/attributes-in-update-passenger-request" + } + }, + "x-abstract": true + }, + "cabin-area": { + "enum": [ + "FirstClass", + "BusinessClass", + "EconomyClass" + ], + "type": "string" + }, + "create-airplane-request-document": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-create-airplane-request" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "create-flight-attendant-request-document": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-create-flight-attendant-request" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "create-flight-request-document": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-create-flight-request" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "create-passenger-request-document": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-create-passenger-request" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "data-in-airplane-response": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-response" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-airplane-response" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-airplane-response" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-links" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-create-airplane-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-create-request" + }, + { + "type": "object", + "properties": { + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-create-airplane-request" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-create-airplane-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-create-flight-attendant-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-create-request" + }, + { + "type": "object", + "properties": { + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-create-flight-attendant-request" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-create-flight-attendant-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-create-flight-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-create-request" + }, + { + "type": "object", + "properties": { + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-create-flight-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-create-passenger-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-create-request" + }, + { + "type": "object", + "properties": { + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-create-passenger-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-flight-attendant-response": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-response" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-flight-attendant-response" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-flight-attendant-response" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-links" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-flight-response": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-response" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-flight-response" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-flight-response" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-links" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-passenger-response": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-response" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-passenger-response" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-links" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-update-airplane-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-update-request" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-update-airplane-request" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-update-airplane-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-update-flight-attendant-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-update-request" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-update-flight-attendant-request" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-update-flight-attendant-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-update-flight-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-update-request" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-update-flight-request" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-update-flight-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-update-passenger-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-update-request" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-update-passenger-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "error-links": { + "type": "object", + "properties": { + "about": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "error-object": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/error-links" + } + ], + "nullable": true + }, + "status": { + "type": "string" + }, + "code": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/error-source" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "error-response-document": { + "required": [ + "errors", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/error-top-level-links" + } + ] + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/error-object" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "error-source": { + "type": "object", + "properties": { + "pointer": { + "type": "string", + "nullable": true + }, + "parameter": { + "type": "string", + "nullable": true + }, + "header": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "error-top-level-links": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "flight-attendant-collection-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-collection-top-level-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/data-in-flight-attendant-response" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "flight-attendant-identifier-collection-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-identifier-collection-top-level-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/flight-attendant-identifier-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "flight-attendant-identifier-in-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifier-in-request" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "flight-attendant-identifier-in-response": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/flight-attendant-resource-type" + } + ] + }, + "id": { + "type": "string" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "flight-attendant-identifier-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-identifier-top-level-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/flight-attendant-identifier-in-response" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "flight-attendant-resource-type": { + "enum": [ + "flight-attendants" + ], + "type": "string" + }, + "flight-collection-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-collection-top-level-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/data-in-flight-response" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "flight-identifier-collection-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-identifier-collection-top-level-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/flight-identifier-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "flight-identifier-in-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifier-in-request" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "flight-identifier-in-response": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/flight-resource-type" + } + ] + }, + "id": { + "type": "string" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "flight-resource-type": { + "enum": [ + "flights" + ], + "type": "string" + }, + "identifier-in-request": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "flight-attendants": "#/components/schemas/flight-attendant-identifier-in-request", + "flights": "#/components/schemas/flight-identifier-in-request", + "passengers": "#/components/schemas/passenger-identifier-in-request" + } + }, + "x-abstract": true + }, + "jsonapi": { + "type": "object", + "properties": { + "version": { + "type": "string" + }, + "ext": { + "type": "array", + "items": { + "type": "string" + } + }, + "profile": { + "type": "array", + "items": { + "type": "string" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "meta": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "nullable-flight-attendant-identifier-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-identifier-top-level-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/flight-attendant-identifier-in-response" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullable-secondary-flight-attendant-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-top-level-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-flight-attendant-response" + } + ], + "nullable": true + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullable-to-one-flight-attendant-in-request": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/flight-attendant-identifier-in-request" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullable-to-one-flight-attendant-in-response": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationship-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/flight-attendant-identifier-in-response" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "passenger-collection-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-collection-top-level-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/data-in-passenger-response" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "passenger-identifier-collection-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-identifier-collection-top-level-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/passenger-identifier-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "passenger-identifier-in-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifier-in-request" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "passenger-identifier-in-response": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/passenger-resource-type" + } + ] + }, + "id": { + "type": "string" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "passenger-resource-type": { + "enum": [ + "passengers" + ], + "type": "string" + }, + "primary-airplane-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-top-level-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-airplane-response" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primary-flight-attendant-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-top-level-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-flight-attendant-response" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primary-flight-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-top-level-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-flight-response" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primary-passenger-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-top-level-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-passenger-response" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "relationship-links": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + } + }, + "additionalProperties": false + }, + "relationships-in-airplane-response": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-response" + }, + { + "type": "object", + "properties": { + "flights": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-response" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationships-in-create-airplane-request": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-create-request" + }, + { + "type": "object", + "properties": { + "flights": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationships-in-create-flight-attendant-request": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-create-request" + }, + { + "type": "object", + "properties": { + "scheduled-for-flights": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + }, + "purser-on-flights": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationships-in-create-flight-request": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-create-request" + }, + { + "required": [ + "purser" + ], + "type": "object", + "properties": { + "cabin-crew-members": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-attendant-in-request" + } + ] + }, + "purser": { + "allOf": [ + { + "$ref": "#/components/schemas/to-one-flight-attendant-in-request" + } + ] + }, + "backup-purser": { + "allOf": [ + { + "$ref": "#/components/schemas/nullable-to-one-flight-attendant-in-request" + } + ] + }, + "passengers": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-passenger-in-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationships-in-create-request": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "airplanes": "#/components/schemas/relationships-in-create-airplane-request", + "flight-attendants": "#/components/schemas/relationships-in-create-flight-attendant-request", + "flights": "#/components/schemas/relationships-in-create-flight-request" + } + }, + "x-abstract": true + }, + "relationships-in-flight-attendant-response": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-response" + }, + { + "type": "object", + "properties": { + "scheduled-for-flights": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-response" + } + ] + }, + "purser-on-flights": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-response" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationships-in-flight-response": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-response" + }, + { + "type": "object", + "properties": { + "cabin-crew-members": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-attendant-in-response" + } + ] + }, + "purser": { + "allOf": [ + { + "$ref": "#/components/schemas/to-one-flight-attendant-in-response" + } + ] + }, + "backup-purser": { + "allOf": [ + { + "$ref": "#/components/schemas/nullable-to-one-flight-attendant-in-response" + } + ] + }, + "passengers": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-passenger-in-response" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationships-in-response": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "airplanes": "#/components/schemas/relationships-in-airplane-response", + "flight-attendants": "#/components/schemas/relationships-in-flight-attendant-response", + "flights": "#/components/schemas/relationships-in-flight-response" + } + }, + "x-abstract": true + }, + "relationships-in-update-airplane-request": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-update-request" + }, + { + "type": "object", + "properties": { + "flights": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationships-in-update-flight-attendant-request": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-update-request" + }, + { + "type": "object", + "properties": { + "scheduled-for-flights": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + }, + "purser-on-flights": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationships-in-update-flight-request": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-update-request" + }, + { + "type": "object", + "properties": { + "cabin-crew-members": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-attendant-in-request" + } + ] + }, + "purser": { + "allOf": [ + { + "$ref": "#/components/schemas/to-one-flight-attendant-in-request" + } + ] + }, + "backup-purser": { + "allOf": [ + { + "$ref": "#/components/schemas/nullable-to-one-flight-attendant-in-request" + } + ] + }, + "passengers": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-passenger-in-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationships-in-update-request": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "airplanes": "#/components/schemas/relationships-in-update-airplane-request", + "flight-attendants": "#/components/schemas/relationships-in-update-flight-attendant-request", + "flights": "#/components/schemas/relationships-in-update-flight-request" + } + }, + "x-abstract": true + }, + "resource-collection-top-level-links": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resource-identifier-collection-top-level-links": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resource-identifier-top-level-links": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resource-in-create-request": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "airplanes": "#/components/schemas/data-in-create-airplane-request", + "flight-attendants": "#/components/schemas/data-in-create-flight-attendant-request", + "flights": "#/components/schemas/data-in-create-flight-request", + "passengers": "#/components/schemas/data-in-create-passenger-request" + } + }, + "x-abstract": true + }, + "resource-in-response": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "airplanes": "#/components/schemas/data-in-airplane-response", + "flight-attendants": "#/components/schemas/data-in-flight-attendant-response", + "flights": "#/components/schemas/data-in-flight-response", + "passengers": "#/components/schemas/data-in-passenger-response" + } + }, + "x-abstract": true + }, + "resource-in-update-request": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "airplanes": "#/components/schemas/data-in-update-airplane-request", + "flight-attendants": "#/components/schemas/data-in-update-flight-attendant-request", + "flights": "#/components/schemas/data-in-update-flight-request", + "passengers": "#/components/schemas/data-in-update-passenger-request" + } + }, + "x-abstract": true + }, + "resource-links": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resource-top-level-links": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resource-type": { + "enum": [ + "airplanes", + "flight-attendants", + "flights", + "passengers" + ], + "type": "string" + }, + "secondary-flight-attendant-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-top-level-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-flight-attendant-response" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "to-many-flight-attendant-in-request": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/flight-attendant-identifier-in-request" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "to-many-flight-attendant-in-response": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationship-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/flight-attendant-identifier-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "to-many-flight-in-request": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/flight-identifier-in-request" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "to-many-flight-in-response": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationship-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/flight-identifier-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "to-many-passenger-in-request": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/passenger-identifier-in-request" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "to-many-passenger-in-response": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationship-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/passenger-identifier-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "to-one-flight-attendant-in-request": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/flight-attendant-identifier-in-request" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "to-one-flight-attendant-in-response": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationship-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/flight-attendant-identifier-in-response" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "update-airplane-request-document": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-update-airplane-request" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "update-flight-attendant-request-document": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-update-flight-attendant-request" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "update-flight-request-document": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-update-flight-request" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "update-passenger-request-document": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-update-passenger-request" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/test/OpenApiTests/LegacyOpenApi/LegacyIntegrationDbContext.cs b/test/OpenApiTests/LegacyOpenApi/LegacyIntegrationDbContext.cs new file mode 100644 index 0000000000..e7503ed5b7 --- /dev/null +++ b/test/OpenApiTests/LegacyOpenApi/LegacyIntegrationDbContext.cs @@ -0,0 +1,33 @@ +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; +using TestBuildingBlocks; + +// @formatter:wrap_chained_method_calls chop_always + +namespace OpenApiTests.LegacyOpenApi; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public sealed class LegacyIntegrationDbContext(DbContextOptions options) + : TestableDbContext(options) +{ + public DbSet Airplanes => Set(); + public DbSet Flights => Set(); + public DbSet FlightAttendants => Set(); + + protected override void OnModelCreating(ModelBuilder builder) + { + builder.Entity() + .HasMany(flight => flight.CabinCrewMembers) + .WithMany(flightAttendant => flightAttendant.ScheduledForFlights); + + builder.Entity() + .HasOne(flight => flight.Purser) + .WithMany(flightAttendant => flightAttendant.PurserOnFlights); + + builder.Entity() + .HasOne(flight => flight.BackupPurser) + .WithMany(); + + base.OnModelCreating(builder); + } +} diff --git a/test/OpenApiTests/LegacyOpenApi/LegacyStartup.cs b/test/OpenApiTests/LegacyOpenApi/LegacyStartup.cs new file mode 100644 index 0000000000..0888be0e1c --- /dev/null +++ b/test/OpenApiTests/LegacyOpenApi/LegacyStartup.cs @@ -0,0 +1,25 @@ +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Resources.Annotations; +using OpenApiTests.NamingConventions.KebabCase; +using TestBuildingBlocks; + +namespace OpenApiTests.LegacyOpenApi; + +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +public sealed class LegacyStartup : OpenApiStartup + where TDbContext : TestableDbContext +{ + protected override void SetJsonApiOptions(JsonApiOptions options) + { + base.SetJsonApiOptions(options); + + options.Namespace = "api"; + options.DefaultAttrCapabilities = AttrCapabilities.AllowView; + options.IncludeJsonApiVersion = true; + options.SerializerOptions.PropertyNamingPolicy = JsonKebabCaseNamingPolicy.Instance; + options.SerializerOptions.DictionaryKeyPolicy = JsonKebabCaseNamingPolicy.Instance; + options.SerializerOptions.Converters.Add(new JsonStringEnumConverter()); + } +} diff --git a/test/OpenApiTests/LegacyOpenApi/LegacyTests.cs b/test/OpenApiTests/LegacyOpenApi/LegacyTests.cs new file mode 100644 index 0000000000..84db211242 --- /dev/null +++ b/test/OpenApiTests/LegacyOpenApi/LegacyTests.cs @@ -0,0 +1,52 @@ +using System.Reflection; +using System.Resources; +using System.Text.Json; +using FluentAssertions; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.LegacyOpenApi; + +public sealed class LegacyTests : OpenApiTestContext, LegacyIntegrationDbContext> +{ + public LegacyTests(ITestOutputHelper testOutputHelper) + { + UseController(); + UseController(); + UseController(); + UseController(); + + SetTestOutputHelper(testOutputHelper); + SwaggerDocumentOutputDirectory = $"{GetType().Namespace!.Replace('.', '/')}/GeneratedSwagger"; + } + + [Fact] + public async Task Retrieved_swagger_document_matches_expected_document() + { + // Act + JsonElement jsonElement = await GetSwaggerDocumentAsync(); + + // Assert + string expectedJsonText = await GetExpectedSwaggerDocumentAsync(); + string actualJsonText = jsonElement.ToString(); + actualJsonText.Should().BeJson(expectedJsonText); + } + + private async Task GetExpectedSwaggerDocumentAsync() + { + string embeddedResourceName = $"{GetType().Namespace!.Replace('/', '.')}.expected-swagger.json"; + var assembly = Assembly.GetExecutingAssembly(); + + await using Stream? stream = assembly.GetManifestResourceStream(embeddedResourceName); + + if (stream == null) + { + throw new MissingManifestResourceException( + $"Failed to load embedded resource '{embeddedResourceName}'. Set Build Action to Embedded Resource in properties."); + } + + using var reader = new StreamReader(stream); + return await reader.ReadToEndAsync(); + } +} diff --git a/test/OpenApiTests/LegacyOpenApi/Passenger.cs b/test/OpenApiTests/LegacyOpenApi/Passenger.cs new file mode 100644 index 0000000000..c939562447 --- /dev/null +++ b/test/OpenApiTests/LegacyOpenApi/Passenger.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.LegacyOpenApi; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.LegacyOpenApi")] +public sealed class Passenger : Identifiable +{ + [Attr(PublicName = "document-number", Capabilities = AttrCapabilities.AllowCreate | AttrCapabilities.AllowChange)] + [MaxLength(9)] + public string PassportNumber { get; set; } = null!; + + [Attr] + public string? FullName { get; set; } + + [Attr] + public CabinArea CabinArea { get; set; } +} diff --git a/test/OpenApiTests/LegacyOpenApi/expected-swagger.json b/test/OpenApiTests/LegacyOpenApi/expected-swagger.json new file mode 100644 index 0000000000..f72814347b --- /dev/null +++ b/test/OpenApiTests/LegacyOpenApi/expected-swagger.json @@ -0,0 +1,8858 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "OpenApiTests", + "version": "1.0" + }, + "servers": [ + { + "url": "http://localhost" + } + ], + "paths": { + "/api/airplanes": { + "get": { + "tags": [ + "airplanes" + ], + "summary": "Retrieves a collection of airplanes.", + "operationId": "get-airplane-collection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found airplanes, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/airplane-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "airplanes" + ], + "summary": "Retrieves a collection of airplanes without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-airplane-collection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "airplanes" + ], + "summary": "Creates a new airplane.", + "operationId": "post-airplane", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the airplane to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/create-airplane-request-document" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The airplane was successfully created, which resulted in additional changes. The newly created airplane is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created airplane can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-airplane-response-document" + } + } + } + }, + "204": { + "description": "The airplane was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/airplanes/{id}": { + "get": { + "tags": [ + "airplanes" + ], + "summary": "Retrieves an individual airplane by its identifier.", + "operationId": "get-airplane", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the airplane to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found airplane.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-airplane-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The airplane does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "airplanes" + ], + "summary": "Retrieves an individual airplane by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-airplane", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the airplane to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The airplane does not exist." + } + } + }, + "patch": { + "tags": [ + "airplanes" + ], + "summary": "Updates an existing airplane.", + "operationId": "patch-airplane", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the airplane to update.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the airplane to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/update-airplane-request-document" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The airplane was successfully updated, which resulted in additional changes. The updated airplane is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-airplane-response-document" + } + } + } + }, + "204": { + "description": "The airplane was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The airplane or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "delete": { + "tags": [ + "airplanes" + ], + "summary": "Deletes an existing airplane by its identifier.", + "operationId": "delete-airplane", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the airplane to delete.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "The airplane was successfully deleted." + }, + "404": { + "description": "The airplane does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/airplanes/{id}/flights": { + "get": { + "tags": [ + "airplanes" + ], + "summary": "Retrieves the related flights of an individual airplane's flights relationship.", + "operationId": "get-airplane-flights", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the airplane whose related flights to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flights, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/flight-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The airplane does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "airplanes" + ], + "summary": "Retrieves the related flights of an individual airplane's flights relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-airplane-flights", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the airplane whose related flights to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The airplane does not exist." + } + } + } + }, + "/api/airplanes/{id}/relationships/flights": { + "get": { + "tags": [ + "airplanes" + ], + "summary": "Retrieves the related flight identities of an individual airplane's flights relationship.", + "operationId": "get-airplane-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the airplane whose related flight identities to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/flight-identifier-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The airplane does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "airplanes" + ], + "summary": "Retrieves the related flight identities of an individual airplane's flights relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-airplane-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the airplane whose related flight identities to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The airplane does not exist." + } + } + }, + "post": { + "tags": [ + "airplanes" + ], + "summary": "Adds existing flights to the flights relationship of an individual airplane.", + "operationId": "post-airplane-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the airplane to add flights to.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flights to add to the flights relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The flights were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The airplane or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "patch": { + "tags": [ + "airplanes" + ], + "summary": "Assigns existing flights to the flights relationship of an individual airplane.", + "operationId": "patch-airplane-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the airplane whose flights relationship to assign.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flights to assign to the flights relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The flights relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The airplane or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "delete": { + "tags": [ + "airplanes" + ], + "summary": "Removes existing flights from the flights relationship of an individual airplane.", + "operationId": "delete-airplane-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the airplane to remove flights from.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flights to remove from the flights relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The flights were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The airplane or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/flight-attendants": { + "get": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves a collection of flight-attendants.", + "operationId": "get-flight-attendant-collection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight-attendants, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/flight-attendant-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves a collection of flight-attendants without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-attendant-collection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "flight-attendants" + ], + "summary": "Creates a new flight-attendant.", + "operationId": "post-flight-attendant", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the flight-attendant to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/create-flight-attendant-request-document" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The flight-attendant was successfully created, which resulted in additional changes. The newly created flight-attendant is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created flight-attendant can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-flight-attendant-response-document" + } + } + } + }, + "204": { + "description": "The flight-attendant was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/flight-attendants/{id}": { + "get": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves an individual flight-attendant by its identifier.", + "operationId": "get-flight-attendant", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight-attendant.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-flight-attendant-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves an individual flight-attendant by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-attendant", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight-attendant does not exist." + } + } + }, + "patch": { + "tags": [ + "flight-attendants" + ], + "summary": "Updates an existing flight-attendant.", + "operationId": "patch-flight-attendant", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant to update.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the flight-attendant to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/update-flight-attendant-request-document" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The flight-attendant was successfully updated, which resulted in additional changes. The updated flight-attendant is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-flight-attendant-response-document" + } + } + } + }, + "204": { + "description": "The flight-attendant was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "delete": { + "tags": [ + "flight-attendants" + ], + "summary": "Deletes an existing flight-attendant by its identifier.", + "operationId": "delete-flight-attendant", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant to delete.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "The flight-attendant was successfully deleted." + }, + "404": { + "description": "The flight-attendant does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/flight-attendants/{id}/purser-on-flights": { + "get": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves the related flights of an individual flight-attendant's purser-on-flights relationship.", + "operationId": "get-flight-attendant-purser-on-flights", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant whose related flights to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flights, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/flight-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves the related flights of an individual flight-attendant's purser-on-flights relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-attendant-purser-on-flights", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant whose related flights to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight-attendant does not exist." + } + } + } + }, + "/api/flight-attendants/{id}/relationships/purser-on-flights": { + "get": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves the related flight identities of an individual flight-attendant's purser-on-flights relationship.", + "operationId": "get-flight-attendant-purser-on-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant whose related flight identities to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/flight-identifier-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves the related flight identities of an individual flight-attendant's purser-on-flights relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-attendant-purser-on-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant whose related flight identities to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight-attendant does not exist." + } + } + }, + "post": { + "tags": [ + "flight-attendants" + ], + "summary": "Adds existing flights to the purser-on-flights relationship of an individual flight-attendant.", + "operationId": "post-flight-attendant-purser-on-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant to add flights to.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flights to add to the purser-on-flights relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The flights were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "patch": { + "tags": [ + "flight-attendants" + ], + "summary": "Assigns existing flights to the purser-on-flights relationship of an individual flight-attendant.", + "operationId": "patch-flight-attendant-purser-on-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant whose purser-on-flights relationship to assign.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flights to assign to the purser-on-flights relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The purser-on-flights relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "delete": { + "tags": [ + "flight-attendants" + ], + "summary": "Removes existing flights from the purser-on-flights relationship of an individual flight-attendant.", + "operationId": "delete-flight-attendant-purser-on-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant to remove flights from.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flights to remove from the purser-on-flights relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The flights were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/flight-attendants/{id}/scheduled-for-flights": { + "get": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves the related flights of an individual flight-attendant's scheduled-for-flights relationship.", + "operationId": "get-flight-attendant-scheduled-for-flights", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant whose related flights to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flights, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/flight-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves the related flights of an individual flight-attendant's scheduled-for-flights relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-attendant-scheduled-for-flights", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant whose related flights to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight-attendant does not exist." + } + } + } + }, + "/api/flight-attendants/{id}/relationships/scheduled-for-flights": { + "get": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves the related flight identities of an individual flight-attendant's scheduled-for-flights relationship.", + "operationId": "get-flight-attendant-scheduled-for-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant whose related flight identities to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/flight-identifier-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flight-attendants" + ], + "summary": "Retrieves the related flight identities of an individual flight-attendant's scheduled-for-flights relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-attendant-scheduled-for-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant whose related flight identities to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight-attendant does not exist." + } + } + }, + "post": { + "tags": [ + "flight-attendants" + ], + "summary": "Adds existing flights to the scheduled-for-flights relationship of an individual flight-attendant.", + "operationId": "post-flight-attendant-scheduled-for-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant to add flights to.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flights to add to the scheduled-for-flights relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The flights were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "patch": { + "tags": [ + "flight-attendants" + ], + "summary": "Assigns existing flights to the scheduled-for-flights relationship of an individual flight-attendant.", + "operationId": "patch-flight-attendant-scheduled-for-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant whose scheduled-for-flights relationship to assign.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flights to assign to the scheduled-for-flights relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The scheduled-for-flights relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "delete": { + "tags": [ + "flight-attendants" + ], + "summary": "Removes existing flights from the scheduled-for-flights relationship of an individual flight-attendant.", + "operationId": "delete-flight-attendant-scheduled-for-flights-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight-attendant to remove flights from.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flights to remove from the scheduled-for-flights relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The flights were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight-attendant or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/flights": { + "get": { + "tags": [ + "flights" + ], + "summary": "Retrieves a collection of flights.", + "operationId": "get-flight-collection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flights, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/flight-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flights" + ], + "summary": "Retrieves a collection of flights without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-collection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "flights" + ], + "summary": "Creates a new flight.", + "operationId": "post-flight", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the flight to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/create-flight-request-document" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The flight was successfully created, which resulted in additional changes. The newly created flight is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created flight can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-flight-response-document" + } + } + } + }, + "204": { + "description": "The flight was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/flights/{id}": { + "get": { + "tags": [ + "flights" + ], + "summary": "Retrieves an individual flight by its identifier.", + "operationId": "get-flight", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-flight-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flights" + ], + "summary": "Retrieves an individual flight by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight does not exist." + } + } + }, + "patch": { + "tags": [ + "flights" + ], + "summary": "Updates an existing flight.", + "operationId": "patch-flight", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight to update.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the flight to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/update-flight-request-document" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The flight was successfully updated, which resulted in additional changes. The updated flight is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-flight-response-document" + } + } + } + }, + "204": { + "description": "The flight was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "delete": { + "tags": [ + "flights" + ], + "summary": "Deletes an existing flight by its identifier.", + "operationId": "delete-flight", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight to delete.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "The flight was successfully deleted." + }, + "404": { + "description": "The flight does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/flights/{id}/backup-purser": { + "get": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendant of an individual flight's backup-purser relationship.", + "operationId": "get-flight-backup-purser", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendant to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight-attendant, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullable-secondary-flight-attendant-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendant of an individual flight's backup-purser relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-backup-purser", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendant to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight does not exist." + } + } + } + }, + "/api/flights/{id}/relationships/backup-purser": { + "get": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendant identity of an individual flight's backup-purser relationship.", + "operationId": "get-flight-backup-purser-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendant identity to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight-attendant identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullable-flight-attendant-identifier-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendant identity of an individual flight's backup-purser relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-backup-purser-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendant identity to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight does not exist." + } + } + }, + "patch": { + "tags": [ + "flights" + ], + "summary": "Clears or assigns an existing flight-attendant to the backup-purser relationship of an individual flight.", + "operationId": "patch-flight-backup-purser-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose backup-purser relationship to assign or clear.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identity of the flight-attendant to assign to the backup-purser relationship, or `null` to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/nullable-to-one-flight-attendant-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The backup-purser relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/flights/{id}/cabin-crew-members": { + "get": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendants of an individual flight's cabin-crew-members relationship.", + "operationId": "get-flight-cabin-crew-members", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendants to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight-attendants, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/flight-attendant-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendants of an individual flight's cabin-crew-members relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-cabin-crew-members", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendants to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight does not exist." + } + } + } + }, + "/api/flights/{id}/relationships/cabin-crew-members": { + "get": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendant identities of an individual flight's cabin-crew-members relationship.", + "operationId": "get-flight-cabin-crew-members-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendant identities to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight-attendant identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/flight-attendant-identifier-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendant identities of an individual flight's cabin-crew-members relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-cabin-crew-members-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendant identities to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight does not exist." + } + } + }, + "post": { + "tags": [ + "flights" + ], + "summary": "Adds existing flight-attendants to the cabin-crew-members relationship of an individual flight.", + "operationId": "post-flight-cabin-crew-members-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight to add flight-attendants to.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flight-attendants to add to the cabin-crew-members relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-attendant-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The flight-attendants were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "patch": { + "tags": [ + "flights" + ], + "summary": "Assigns existing flight-attendants to the cabin-crew-members relationship of an individual flight.", + "operationId": "patch-flight-cabin-crew-members-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose cabin-crew-members relationship to assign.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flight-attendants to assign to the cabin-crew-members relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-attendant-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The cabin-crew-members relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "delete": { + "tags": [ + "flights" + ], + "summary": "Removes existing flight-attendants from the cabin-crew-members relationship of an individual flight.", + "operationId": "delete-flight-cabin-crew-members-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight to remove flight-attendants from.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the flight-attendants to remove from the cabin-crew-members relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-attendant-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The flight-attendants were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/flights/{id}/passengers": { + "get": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related passengers of an individual flight's passengers relationship.", + "operationId": "get-flight-passengers", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related passengers to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found passengers, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/passenger-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related passengers of an individual flight's passengers relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-passengers", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related passengers to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight does not exist." + } + } + } + }, + "/api/flights/{id}/relationships/passengers": { + "get": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related passenger identities of an individual flight's passengers relationship.", + "operationId": "get-flight-passengers-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related passenger identities to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found passenger identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/passenger-identifier-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related passenger identities of an individual flight's passengers relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-passengers-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related passenger identities to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight does not exist." + } + } + }, + "post": { + "tags": [ + "flights" + ], + "summary": "Adds existing passengers to the passengers relationship of an individual flight.", + "operationId": "post-flight-passengers-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight to add passengers to.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the passengers to add to the passengers relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-passenger-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The passengers were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "patch": { + "tags": [ + "flights" + ], + "summary": "Assigns existing passengers to the passengers relationship of an individual flight.", + "operationId": "patch-flight-passengers-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose passengers relationship to assign.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the passengers to assign to the passengers relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-passenger-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The passengers relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "delete": { + "tags": [ + "flights" + ], + "summary": "Removes existing passengers from the passengers relationship of an individual flight.", + "operationId": "delete-flight-passengers-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight to remove passengers from.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identities of the passengers to remove from the passengers relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-passenger-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The passengers were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/flights/{id}/purser": { + "get": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendant of an individual flight's purser relationship.", + "operationId": "get-flight-purser", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendant to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight-attendant, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/secondary-flight-attendant-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendant of an individual flight's purser relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-purser", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendant to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight does not exist." + } + } + } + }, + "/api/flights/{id}/relationships/purser": { + "get": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendant identity of an individual flight's purser relationship.", + "operationId": "get-flight-purser-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendant identity to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found flight-attendant identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/flight-attendant-identifier-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "flights" + ], + "summary": "Retrieves the related flight-attendant identity of an individual flight's purser relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-flight-purser-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose related flight-attendant identity to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The flight does not exist." + } + } + }, + "patch": { + "tags": [ + "flights" + ], + "summary": "Assigns an existing flight-attendant to the purser relationship of an individual flight.", + "operationId": "patch-flight-purser-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the flight whose purser relationship to assign.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The identity of the flight-attendant to assign to the purser relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-one-flight-attendant-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The purser relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The flight or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/passengers": { + "get": { + "tags": [ + "passengers" + ], + "summary": "Retrieves a collection of passengers.", + "operationId": "get-passenger-collection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found passengers, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/passenger-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "passengers" + ], + "summary": "Retrieves a collection of passengers without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-passenger-collection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "passengers" + ], + "summary": "Creates a new passenger.", + "operationId": "post-passenger", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the passenger to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/create-passenger-request-document" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The passenger was successfully created, which resulted in additional changes. The newly created passenger is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created passenger can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-passenger-response-document" + } + } + } + }, + "204": { + "description": "The passenger was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/api/passengers/{id}": { + "get": { + "tags": [ + "passengers" + ], + "summary": "Retrieves an individual passenger by its identifier.", + "operationId": "get-passenger", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the passenger to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found passenger.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-passenger-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The passenger does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "passengers" + ], + "summary": "Retrieves an individual passenger by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-passenger", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the passenger to retrieve.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The passenger does not exist." + } + } + }, + "patch": { + "tags": [ + "passengers" + ], + "summary": "Updates an existing passenger.", + "operationId": "patch-passenger", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the passenger to update.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the passenger to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/update-passenger-request-document" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The passenger was successfully updated, which resulted in additional changes. The updated passenger is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-passenger-response-document" + } + } + } + }, + "204": { + "description": "The passenger was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The passenger or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "delete": { + "tags": [ + "passengers" + ], + "summary": "Deletes an existing passenger by its identifier.", + "operationId": "delete-passenger", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the passenger to delete.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "The passenger was successfully deleted." + }, + "404": { + "description": "The passenger does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "aircraft-kind": { + "enum": [ + "Turboprops", + "LightJet", + "MidSizeJet", + "JumboJet" + ], + "type": "string" + }, + "airline": { + "enum": [ + "DeltaAirLines", + "LufthansaGroup", + "AirFranceKlm" + ], + "type": "string", + "description": "Lists the various airlines used in this API." + }, + "airplane-collection-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-collection-top-level-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/data-in-airplane-response" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "attributes-in-airplane-response": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-response" + }, + { + "type": "object", + "properties": { + "name": { + "maxLength": 255, + "type": "string" + }, + "serial-number": { + "maxLength": 16, + "type": "string", + "nullable": true + }, + "airtime-in-hours": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "last-serviced-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "manufactured-at": { + "type": "string", + "description": "Gets the day on which this airplane was manufactured.", + "format": "date-time" + }, + "is-in-maintenance": { + "type": "boolean" + }, + "manufactured-in-city": { + "maxLength": 85, + "type": "string", + "nullable": true + }, + "kind": { + "allOf": [ + { + "$ref": "#/components/schemas/aircraft-kind" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-create-airplane-request": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-create-request" + }, + { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "maxLength": 255, + "type": "string" + }, + "serial-number": { + "maxLength": 16, + "type": "string", + "nullable": true + }, + "airtime-in-hours": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "last-serviced-at": { + "type": "string", + "format": "date-time", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-create-flight-attendant-request": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-create-request" + }, + { + "required": [ + "email-address", + "profile-image-url" + ], + "type": "object", + "properties": { + "email-address": { + "minLength": 1, + "type": "string", + "format": "email" + }, + "age": { + "maximum": 75, + "minimum": 18, + "type": "integer", + "format": "int32" + }, + "profile-image-url": { + "type": "string", + "format": "uri" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-create-passenger-request": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-create-request" + }, + { + "required": [ + "document-number" + ], + "type": "object", + "properties": { + "document-number": { + "maxLength": 9, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-create-request": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "airplanes": "#/components/schemas/attributes-in-create-airplane-request", + "flight-attendants": "#/components/schemas/attributes-in-create-flight-attendant-request", + "passengers": "#/components/schemas/attributes-in-create-passenger-request" + } + }, + "x-abstract": true + }, + "attributes-in-flight-attendant-response": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-response" + }, + { + "type": "object", + "properties": { + "email-address": { + "minLength": 1, + "type": "string", + "format": "email" + }, + "age": { + "maximum": 75, + "minimum": 18, + "type": "integer", + "format": "int32" + }, + "profile-image-url": { + "type": "string", + "format": "uri" + }, + "distance-traveled-in-kilometers": { + "type": "integer", + "format": "int64" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-flight-response": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-response" + }, + { + "type": "object", + "properties": { + "final-destination": { + "maxLength": 40, + "type": "string" + }, + "stop-over-destination": { + "maxLength": 2000, + "type": "string", + "nullable": true + }, + "operated-by": { + "allOf": [ + { + "$ref": "#/components/schemas/airline" + } + ] + }, + "departs-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "arrives-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "services-on-board": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-passenger-response": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-response" + }, + { + "type": "object", + "properties": { + "full-name": { + "type": "string", + "nullable": true + }, + "cabin-area": { + "allOf": [ + { + "$ref": "#/components/schemas/cabin-area" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-response": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "airplanes": "#/components/schemas/attributes-in-airplane-response", + "flight-attendants": "#/components/schemas/attributes-in-flight-attendant-response", + "flights": "#/components/schemas/attributes-in-flight-response", + "passengers": "#/components/schemas/attributes-in-passenger-response" + } + }, + "x-abstract": true + }, + "attributes-in-update-airplane-request": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-update-request" + }, + { + "type": "object", + "properties": { + "name": { + "maxLength": 255, + "type": "string" + }, + "serial-number": { + "maxLength": 16, + "type": "string", + "nullable": true + }, + "airtime-in-hours": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "last-serviced-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "is-in-maintenance": { + "type": "boolean" + }, + "manufactured-in-city": { + "maxLength": 85, + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-update-flight-attendant-request": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-update-request" + }, + { + "type": "object", + "properties": { + "email-address": { + "minLength": 1, + "type": "string", + "format": "email" + }, + "age": { + "maximum": 75, + "minimum": 18, + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-update-flight-request": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-update-request" + }, + { + "type": "object", + "properties": { + "final-destination": { + "maxLength": 40, + "type": "string" + }, + "stop-over-destination": { + "maxLength": 2000, + "type": "string", + "nullable": true + }, + "operated-by": { + "allOf": [ + { + "$ref": "#/components/schemas/airline" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-update-passenger-request": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-update-request" + }, + { + "type": "object", + "properties": { + "document-number": { + "maxLength": 9, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-update-request": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "airplanes": "#/components/schemas/attributes-in-update-airplane-request", + "flight-attendants": "#/components/schemas/attributes-in-update-flight-attendant-request", + "flights": "#/components/schemas/attributes-in-update-flight-request", + "passengers": "#/components/schemas/attributes-in-update-passenger-request" + } + }, + "x-abstract": true + }, + "cabin-area": { + "enum": [ + "FirstClass", + "BusinessClass", + "EconomyClass" + ], + "type": "string" + }, + "create-airplane-request-document": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-create-airplane-request" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "create-flight-attendant-request-document": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-create-flight-attendant-request" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "create-flight-request-document": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-create-flight-request" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "create-passenger-request-document": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-create-passenger-request" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "data-in-airplane-response": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-response" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-airplane-response" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-airplane-response" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-links" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-create-airplane-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-create-request" + }, + { + "type": "object", + "properties": { + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-create-airplane-request" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-create-airplane-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-create-flight-attendant-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-create-request" + }, + { + "type": "object", + "properties": { + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-create-flight-attendant-request" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-create-flight-attendant-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-create-flight-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-create-request" + }, + { + "type": "object", + "properties": { + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-create-flight-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-create-passenger-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-create-request" + }, + { + "type": "object", + "properties": { + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-create-passenger-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-flight-attendant-response": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-response" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-flight-attendant-response" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-flight-attendant-response" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-links" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-flight-response": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-response" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-flight-response" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-flight-response" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-links" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-passenger-response": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-response" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-passenger-response" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-links" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-update-airplane-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-update-request" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-update-airplane-request" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-update-airplane-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-update-flight-attendant-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-update-request" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-update-flight-attendant-request" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-update-flight-attendant-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-update-flight-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-update-request" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-update-flight-request" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-update-flight-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-update-passenger-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-update-request" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-update-passenger-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "error-links": { + "type": "object", + "properties": { + "about": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "error-object": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/error-links" + } + ], + "nullable": true + }, + "status": { + "type": "string" + }, + "code": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/error-source" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "error-response-document": { + "required": [ + "errors", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/error-top-level-links" + } + ] + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/error-object" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "error-source": { + "type": "object", + "properties": { + "pointer": { + "type": "string", + "nullable": true + }, + "parameter": { + "type": "string", + "nullable": true + }, + "header": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "error-top-level-links": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "flight-attendant-collection-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-collection-top-level-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/data-in-flight-attendant-response" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "flight-attendant-identifier-collection-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-identifier-collection-top-level-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/flight-attendant-identifier-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "flight-attendant-identifier-in-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifier-in-request" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "flight-attendant-identifier-in-response": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/flight-attendant-resource-type" + } + ] + }, + "id": { + "type": "string" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "flight-attendant-identifier-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-identifier-top-level-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/flight-attendant-identifier-in-response" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "flight-attendant-resource-type": { + "enum": [ + "flight-attendants" + ], + "type": "string" + }, + "flight-collection-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-collection-top-level-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/data-in-flight-response" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "flight-identifier-collection-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-identifier-collection-top-level-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/flight-identifier-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "flight-identifier-in-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifier-in-request" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "flight-identifier-in-response": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/flight-resource-type" + } + ] + }, + "id": { + "type": "string" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "flight-resource-type": { + "enum": [ + "flights" + ], + "type": "string" + }, + "identifier-in-request": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "flight-attendants": "#/components/schemas/flight-attendant-identifier-in-request", + "flights": "#/components/schemas/flight-identifier-in-request", + "passengers": "#/components/schemas/passenger-identifier-in-request" + } + }, + "x-abstract": true + }, + "jsonapi": { + "type": "object", + "properties": { + "version": { + "type": "string" + }, + "ext": { + "type": "array", + "items": { + "type": "string" + } + }, + "profile": { + "type": "array", + "items": { + "type": "string" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "meta": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "nullable-flight-attendant-identifier-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-identifier-top-level-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/flight-attendant-identifier-in-response" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullable-secondary-flight-attendant-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-top-level-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-flight-attendant-response" + } + ], + "nullable": true + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullable-to-one-flight-attendant-in-request": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/flight-attendant-identifier-in-request" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullable-to-one-flight-attendant-in-response": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationship-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/flight-attendant-identifier-in-response" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "passenger-collection-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-collection-top-level-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/data-in-passenger-response" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "passenger-identifier-collection-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-identifier-collection-top-level-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/passenger-identifier-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "passenger-identifier-in-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifier-in-request" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "passenger-identifier-in-response": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/passenger-resource-type" + } + ] + }, + "id": { + "type": "string" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "passenger-resource-type": { + "enum": [ + "passengers" + ], + "type": "string" + }, + "primary-airplane-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-top-level-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-airplane-response" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primary-flight-attendant-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-top-level-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-flight-attendant-response" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primary-flight-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-top-level-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-flight-response" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primary-passenger-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-top-level-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-passenger-response" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "relationship-links": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + } + }, + "additionalProperties": false + }, + "relationships-in-airplane-response": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-response" + }, + { + "type": "object", + "properties": { + "flights": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-response" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationships-in-create-airplane-request": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-create-request" + }, + { + "type": "object", + "properties": { + "flights": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationships-in-create-flight-attendant-request": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-create-request" + }, + { + "type": "object", + "properties": { + "scheduled-for-flights": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + }, + "purser-on-flights": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationships-in-create-flight-request": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-create-request" + }, + { + "required": [ + "purser" + ], + "type": "object", + "properties": { + "cabin-crew-members": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-attendant-in-request" + } + ] + }, + "purser": { + "allOf": [ + { + "$ref": "#/components/schemas/to-one-flight-attendant-in-request" + } + ] + }, + "backup-purser": { + "allOf": [ + { + "$ref": "#/components/schemas/nullable-to-one-flight-attendant-in-request" + } + ] + }, + "passengers": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-passenger-in-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationships-in-create-request": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "airplanes": "#/components/schemas/relationships-in-create-airplane-request", + "flight-attendants": "#/components/schemas/relationships-in-create-flight-attendant-request", + "flights": "#/components/schemas/relationships-in-create-flight-request" + } + }, + "x-abstract": true + }, + "relationships-in-flight-attendant-response": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-response" + }, + { + "type": "object", + "properties": { + "scheduled-for-flights": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-response" + } + ] + }, + "purser-on-flights": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-response" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationships-in-flight-response": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-response" + }, + { + "type": "object", + "properties": { + "cabin-crew-members": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-attendant-in-response" + } + ] + }, + "purser": { + "allOf": [ + { + "$ref": "#/components/schemas/to-one-flight-attendant-in-response" + } + ] + }, + "backup-purser": { + "allOf": [ + { + "$ref": "#/components/schemas/nullable-to-one-flight-attendant-in-response" + } + ] + }, + "passengers": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-passenger-in-response" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationships-in-response": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "airplanes": "#/components/schemas/relationships-in-airplane-response", + "flight-attendants": "#/components/schemas/relationships-in-flight-attendant-response", + "flights": "#/components/schemas/relationships-in-flight-response" + } + }, + "x-abstract": true + }, + "relationships-in-update-airplane-request": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-update-request" + }, + { + "type": "object", + "properties": { + "flights": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationships-in-update-flight-attendant-request": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-update-request" + }, + { + "type": "object", + "properties": { + "scheduled-for-flights": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + }, + "purser-on-flights": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-in-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationships-in-update-flight-request": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-update-request" + }, + { + "type": "object", + "properties": { + "cabin-crew-members": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-flight-attendant-in-request" + } + ] + }, + "purser": { + "allOf": [ + { + "$ref": "#/components/schemas/to-one-flight-attendant-in-request" + } + ] + }, + "backup-purser": { + "allOf": [ + { + "$ref": "#/components/schemas/nullable-to-one-flight-attendant-in-request" + } + ] + }, + "passengers": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-passenger-in-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationships-in-update-request": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "airplanes": "#/components/schemas/relationships-in-update-airplane-request", + "flight-attendants": "#/components/schemas/relationships-in-update-flight-attendant-request", + "flights": "#/components/schemas/relationships-in-update-flight-request" + } + }, + "x-abstract": true + }, + "resource-collection-top-level-links": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resource-identifier-collection-top-level-links": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resource-identifier-top-level-links": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resource-in-create-request": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "airplanes": "#/components/schemas/data-in-create-airplane-request", + "flight-attendants": "#/components/schemas/data-in-create-flight-attendant-request", + "flights": "#/components/schemas/data-in-create-flight-request", + "passengers": "#/components/schemas/data-in-create-passenger-request" + } + }, + "x-abstract": true + }, + "resource-in-response": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "airplanes": "#/components/schemas/data-in-airplane-response", + "flight-attendants": "#/components/schemas/data-in-flight-attendant-response", + "flights": "#/components/schemas/data-in-flight-response", + "passengers": "#/components/schemas/data-in-passenger-response" + } + }, + "x-abstract": true + }, + "resource-in-update-request": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "airplanes": "#/components/schemas/data-in-update-airplane-request", + "flight-attendants": "#/components/schemas/data-in-update-flight-attendant-request", + "flights": "#/components/schemas/data-in-update-flight-request", + "passengers": "#/components/schemas/data-in-update-passenger-request" + } + }, + "x-abstract": true + }, + "resource-links": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resource-top-level-links": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resource-type": { + "enum": [ + "airplanes", + "flight-attendants", + "flights", + "passengers" + ], + "type": "string" + }, + "secondary-flight-attendant-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-top-level-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-flight-attendant-response" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "to-many-flight-attendant-in-request": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/flight-attendant-identifier-in-request" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "to-many-flight-attendant-in-response": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationship-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/flight-attendant-identifier-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "to-many-flight-in-request": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/flight-identifier-in-request" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "to-many-flight-in-response": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationship-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/flight-identifier-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "to-many-passenger-in-request": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/passenger-identifier-in-request" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "to-many-passenger-in-response": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationship-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/passenger-identifier-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "to-one-flight-attendant-in-request": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/flight-attendant-identifier-in-request" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "to-one-flight-attendant-in-response": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationship-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/flight-attendant-identifier-in-response" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "update-airplane-request-document": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-update-airplane-request" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "update-flight-attendant-request-document": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-update-flight-attendant-request" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "update-flight-request-document": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-update-flight-request" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "update-passenger-request-document": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-update-passenger-request" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/test/OpenApiTests/Links/Accommodation.cs b/test/OpenApiTests/Links/Accommodation.cs new file mode 100644 index 0000000000..5a793da701 --- /dev/null +++ b/test/OpenApiTests/Links/Accommodation.cs @@ -0,0 +1,13 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.Links; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.Links")] +public sealed class Accommodation : Identifiable +{ + [Attr] + public string Address { get; set; } = null!; +} diff --git a/test/OpenApiTests/Links/Disabled/LinksDisabledTests.cs b/test/OpenApiTests/Links/Disabled/LinksDisabledTests.cs new file mode 100644 index 0000000000..c236ef9b61 --- /dev/null +++ b/test/OpenApiTests/Links/Disabled/LinksDisabledTests.cs @@ -0,0 +1,120 @@ +using System.Text.Json; +using FluentAssertions; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Resources.Annotations; +using Microsoft.Extensions.DependencyInjection; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.Links.Disabled; + +public sealed class LinksDisabledTests : IClassFixture, LinkDbContext>> +{ + private readonly OpenApiTestContext, LinkDbContext> _testContext; + + public LinksDisabledTests(OpenApiTestContext, LinkDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + + testContext.SetTestOutputHelper(testOutputHelper); + + var options = (JsonApiOptions)testContext.Factory.Services.GetRequiredService(); + options.TopLevelLinks = LinkTypes.None; + options.ResourceLinks = LinkTypes.NotConfigured; + options.RelationshipLinks = LinkTypes.None; + } + + [Theory] + [InlineData("resourceTopLevelLinks")] + [InlineData("resourceCollectionTopLevelLinks")] + [InlineData("resourceIdentifierTopLevelLinks")] + [InlineData("resourceIdentifierCollectionTopLevelLinks")] + [InlineData("errorTopLevelLinks")] + [InlineData("relationshipLinks")] + [InlineData("resourceLinks")] + public async Task All_configurable_link_schemas_are_hidden(string schemaId) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas").With(schemasElement => + { + schemasElement.Should().NotContainPath(schemaId); + }); + } + + [Fact] + public async Task Error_links_schema_is_visible() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.errorLinks").With(linksElement => + { + linksElement.Should().NotContainPath("required"); + + linksElement.Should().ContainPath("properties").With(propertiesElement => + { + string[] linkPropertyNames = propertiesElement.EnumerateObject().Select(propertyElement => propertyElement.Name).ToArray(); + + linkPropertyNames.Should().HaveCount(2); + linkPropertyNames[0].Should().Be("about"); + linkPropertyNames[1].Should().Be("type"); + }); + }); + } + + [Theory] + [InlineData("primaryAccommodationResponseDocument")] + [InlineData("secondaryAccommodationResponseDocument")] + [InlineData("primaryExcursionResponseDocument")] + [InlineData("primaryTransportResponseDocument")] + [InlineData("nullableSecondaryTransportResponseDocument")] + [InlineData("primaryVacationResponseDocument")] + [InlineData("accommodationCollectionResponseDocument")] + [InlineData("excursionCollectionResponseDocument")] + [InlineData("transportCollectionResponseDocument")] + [InlineData("vacationCollectionResponseDocument")] + [InlineData("accommodationIdentifierResponseDocument")] + [InlineData("nullableTransportIdentifierResponseDocument")] + [InlineData("excursionIdentifierCollectionResponseDocument")] + [InlineData("errorResponseDocument")] + [InlineData("toOneAccommodationInResponse")] + [InlineData("toManyExcursionInResponse")] + [InlineData("nullableToOneTransportInResponse")] + [InlineData("dataInAccommodationResponse.allOf[1]")] + [InlineData("dataInExcursionResponse.allOf[1]")] + [InlineData("dataInTransportResponse.allOf[1]")] + [InlineData("dataInVacationResponse.allOf[1]")] + public async Task All_container_schemas_contain_no_link_property(string containerSchemaId) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas").With(schemasElement => + { + schemasElement.Should().ContainPath(containerSchemaId).With(containerElement => + { + if (containerElement.TryGetProperty("required", out JsonElement requiredElement)) + { + requiredElement.Should().NotContainArrayElement("links"); + } + else + { + containerElement.Should().NotContainPath("required"); + } + + containerElement.Should().NotContainPath("properties.links"); + }); + }); + } +} diff --git a/test/OpenApiTests/Links/Enabled/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/Links/Enabled/GeneratedSwagger/swagger.g.json new file mode 100644 index 0000000000..b72c15aecb --- /dev/null +++ b/test/OpenApiTests/Links/Enabled/GeneratedSwagger/swagger.g.json @@ -0,0 +1,6013 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "OpenApiTests", + "version": "1.0" + }, + "servers": [ + { + "url": "http://localhost" + } + ], + "paths": { + "/accommodations": { + "get": { + "tags": [ + "accommodations" + ], + "summary": "Retrieves a collection of accommodations.", + "operationId": "getAccommodationCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found accommodations, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/accommodationCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "accommodations" + ], + "summary": "Retrieves a collection of accommodations without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headAccommodationCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "accommodations" + ], + "summary": "Creates a new accommodation.", + "operationId": "postAccommodation", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the accommodation to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createAccommodationRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The accommodation was successfully created, which resulted in additional changes. The newly created accommodation is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created accommodation can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryAccommodationResponseDocument" + } + } + } + }, + "204": { + "description": "The accommodation was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/accommodations/{id}": { + "get": { + "tags": [ + "accommodations" + ], + "summary": "Retrieves an individual accommodation by its identifier.", + "operationId": "getAccommodation", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the accommodation to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found accommodation.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryAccommodationResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The accommodation does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "accommodations" + ], + "summary": "Retrieves an individual accommodation by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headAccommodation", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the accommodation to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The accommodation does not exist." + } + } + }, + "patch": { + "tags": [ + "accommodations" + ], + "summary": "Updates an existing accommodation.", + "operationId": "patchAccommodation", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the accommodation to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the accommodation to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateAccommodationRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The accommodation was successfully updated, which resulted in additional changes. The updated accommodation is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryAccommodationResponseDocument" + } + } + } + }, + "204": { + "description": "The accommodation was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The accommodation or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "accommodations" + ], + "summary": "Deletes an existing accommodation by its identifier.", + "operationId": "deleteAccommodation", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the accommodation to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "The accommodation was successfully deleted." + }, + "404": { + "description": "The accommodation does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/excursions": { + "get": { + "tags": [ + "excursions" + ], + "summary": "Retrieves a collection of excursions.", + "operationId": "getExcursionCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found excursions, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/excursionCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "excursions" + ], + "summary": "Retrieves a collection of excursions without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headExcursionCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "excursions" + ], + "summary": "Creates a new excursion.", + "operationId": "postExcursion", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the excursion to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createExcursionRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The excursion was successfully created, which resulted in additional changes. The newly created excursion is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created excursion can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryExcursionResponseDocument" + } + } + } + }, + "204": { + "description": "The excursion was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/excursions/{id}": { + "get": { + "tags": [ + "excursions" + ], + "summary": "Retrieves an individual excursion by its identifier.", + "operationId": "getExcursion", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the excursion to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found excursion.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryExcursionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The excursion does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "excursions" + ], + "summary": "Retrieves an individual excursion by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headExcursion", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the excursion to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The excursion does not exist." + } + } + }, + "patch": { + "tags": [ + "excursions" + ], + "summary": "Updates an existing excursion.", + "operationId": "patchExcursion", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the excursion to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the excursion to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateExcursionRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The excursion was successfully updated, which resulted in additional changes. The updated excursion is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryExcursionResponseDocument" + } + } + } + }, + "204": { + "description": "The excursion was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The excursion or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "excursions" + ], + "summary": "Deletes an existing excursion by its identifier.", + "operationId": "deleteExcursion", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the excursion to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "The excursion was successfully deleted." + }, + "404": { + "description": "The excursion does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/transports": { + "get": { + "tags": [ + "transports" + ], + "summary": "Retrieves a collection of transports.", + "operationId": "getTransportCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found transports, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/transportCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "transports" + ], + "summary": "Retrieves a collection of transports without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headTransportCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "transports" + ], + "summary": "Creates a new transport.", + "operationId": "postTransport", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the transport to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createTransportRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The transport was successfully created, which resulted in additional changes. The newly created transport is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created transport can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryTransportResponseDocument" + } + } + } + }, + "204": { + "description": "The transport was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/transports/{id}": { + "get": { + "tags": [ + "transports" + ], + "summary": "Retrieves an individual transport by its identifier.", + "operationId": "getTransport", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the transport to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found transport.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryTransportResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The transport does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "transports" + ], + "summary": "Retrieves an individual transport by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headTransport", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the transport to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The transport does not exist." + } + } + }, + "patch": { + "tags": [ + "transports" + ], + "summary": "Updates an existing transport.", + "operationId": "patchTransport", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the transport to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the transport to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateTransportRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The transport was successfully updated, which resulted in additional changes. The updated transport is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryTransportResponseDocument" + } + } + } + }, + "204": { + "description": "The transport was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The transport or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "transports" + ], + "summary": "Deletes an existing transport by its identifier.", + "operationId": "deleteTransport", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the transport to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "The transport was successfully deleted." + }, + "404": { + "description": "The transport does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/vacations": { + "get": { + "tags": [ + "vacations" + ], + "summary": "Retrieves a collection of vacations.", + "operationId": "getVacationCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found vacations, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/vacationCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "vacations" + ], + "summary": "Retrieves a collection of vacations without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headVacationCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "vacations" + ], + "summary": "Creates a new vacation.", + "operationId": "postVacation", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the vacation to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createVacationRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The vacation was successfully created, which resulted in additional changes. The newly created vacation is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created vacation can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryVacationResponseDocument" + } + } + } + }, + "204": { + "description": "The vacation was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/vacations/{id}": { + "get": { + "tags": [ + "vacations" + ], + "summary": "Retrieves an individual vacation by its identifier.", + "operationId": "getVacation", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the vacation to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found vacation.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryVacationResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The vacation does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "vacations" + ], + "summary": "Retrieves an individual vacation by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headVacation", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the vacation to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The vacation does not exist." + } + } + }, + "patch": { + "tags": [ + "vacations" + ], + "summary": "Updates an existing vacation.", + "operationId": "patchVacation", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the vacation to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the vacation to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateVacationRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The vacation was successfully updated, which resulted in additional changes. The updated vacation is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryVacationResponseDocument" + } + } + } + }, + "204": { + "description": "The vacation was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The vacation or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "vacations" + ], + "summary": "Deletes an existing vacation by its identifier.", + "operationId": "deleteVacation", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the vacation to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "The vacation was successfully deleted." + }, + "404": { + "description": "The vacation does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/vacations/{id}/accommodation": { + "get": { + "tags": [ + "vacations" + ], + "summary": "Retrieves the related accommodation of an individual vacation's accommodation relationship.", + "operationId": "getVacationAccommodation", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the vacation whose related accommodation to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found accommodation, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/secondaryAccommodationResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The vacation does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "vacations" + ], + "summary": "Retrieves the related accommodation of an individual vacation's accommodation relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headVacationAccommodation", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the vacation whose related accommodation to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The vacation does not exist." + } + } + } + }, + "/vacations/{id}/relationships/accommodation": { + "get": { + "tags": [ + "vacations" + ], + "summary": "Retrieves the related accommodation identity of an individual vacation's accommodation relationship.", + "operationId": "getVacationAccommodationRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the vacation whose related accommodation identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found accommodation identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/accommodationIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The vacation does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "vacations" + ], + "summary": "Retrieves the related accommodation identity of an individual vacation's accommodation relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headVacationAccommodationRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the vacation whose related accommodation identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The vacation does not exist." + } + } + }, + "patch": { + "tags": [ + "vacations" + ], + "summary": "Assigns an existing accommodation to the accommodation relationship of an individual vacation.", + "operationId": "patchVacationAccommodationRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the vacation whose accommodation relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identity of the accommodation to assign to the accommodation relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneAccommodationInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The accommodation relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The vacation or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/vacations/{id}/excursions": { + "get": { + "tags": [ + "vacations" + ], + "summary": "Retrieves the related excursions of an individual vacation's excursions relationship.", + "operationId": "getVacationExcursions", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the vacation whose related excursions to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found excursions, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/excursionCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The vacation does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "vacations" + ], + "summary": "Retrieves the related excursions of an individual vacation's excursions relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headVacationExcursions", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the vacation whose related excursions to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The vacation does not exist." + } + } + } + }, + "/vacations/{id}/relationships/excursions": { + "get": { + "tags": [ + "vacations" + ], + "summary": "Retrieves the related excursion identities of an individual vacation's excursions relationship.", + "operationId": "getVacationExcursionsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the vacation whose related excursion identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found excursion identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/excursionIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The vacation does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "vacations" + ], + "summary": "Retrieves the related excursion identities of an individual vacation's excursions relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headVacationExcursionsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the vacation whose related excursion identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The vacation does not exist." + } + } + }, + "post": { + "tags": [ + "vacations" + ], + "summary": "Adds existing excursions to the excursions relationship of an individual vacation.", + "operationId": "postVacationExcursionsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the vacation to add excursions to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the excursions to add to the excursions relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyExcursionInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The excursions were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The vacation or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "vacations" + ], + "summary": "Assigns existing excursions to the excursions relationship of an individual vacation.", + "operationId": "patchVacationExcursionsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the vacation whose excursions relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the excursions to assign to the excursions relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyExcursionInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The excursions relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The vacation or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "vacations" + ], + "summary": "Removes existing excursions from the excursions relationship of an individual vacation.", + "operationId": "deleteVacationExcursionsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the vacation to remove excursions from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the excursions to remove from the excursions relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyExcursionInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The excursions were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The vacation or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/vacations/{id}/transport": { + "get": { + "tags": [ + "vacations" + ], + "summary": "Retrieves the related transport of an individual vacation's transport relationship.", + "operationId": "getVacationTransport", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the vacation whose related transport to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found transport, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullableSecondaryTransportResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The vacation does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "vacations" + ], + "summary": "Retrieves the related transport of an individual vacation's transport relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headVacationTransport", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the vacation whose related transport to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The vacation does not exist." + } + } + } + }, + "/vacations/{id}/relationships/transport": { + "get": { + "tags": [ + "vacations" + ], + "summary": "Retrieves the related transport identity of an individual vacation's transport relationship.", + "operationId": "getVacationTransportRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the vacation whose related transport identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found transport identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullableTransportIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The vacation does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "vacations" + ], + "summary": "Retrieves the related transport identity of an individual vacation's transport relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headVacationTransportRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the vacation whose related transport identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The vacation does not exist." + } + } + }, + "patch": { + "tags": [ + "vacations" + ], + "summary": "Clears or assigns an existing transport to the transport relationship of an individual vacation.", + "operationId": "patchVacationTransportRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the vacation whose transport relationship to assign or clear.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identity of the transport to assign to the transport relationship, or `null` to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneTransportInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The transport relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The vacation or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "accommodationCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInAccommodationResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "accommodationIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "accommodationIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/accommodationResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "accommodationIdentifierResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/accommodationIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "accommodationResourceType": { + "enum": [ + "accommodations" + ], + "type": "string" + }, + "attributesInAccommodationResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "address": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateAccommodationRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "address" + ], + "type": "object", + "properties": { + "address": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateExcursionRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "description", + "occursAt" + ], + "type": "object", + "properties": { + "occursAt": { + "type": "string", + "format": "date-time" + }, + "description": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "accommodations": "#/components/schemas/attributesInCreateAccommodationRequest", + "excursions": "#/components/schemas/attributesInCreateExcursionRequest", + "transports": "#/components/schemas/attributesInCreateTransportRequest", + "vacations": "#/components/schemas/attributesInCreateVacationRequest" + } + }, + "x-abstract": true + }, + "attributesInCreateTransportRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "durationInMinutes", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/transportType" + } + ] + }, + "durationInMinutes": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateVacationRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "endsAt", + "startsAt" + ], + "type": "object", + "properties": { + "startsAt": { + "type": "string", + "format": "date-time" + }, + "endsAt": { + "type": "string", + "format": "date-time" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInExcursionResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "occursAt": { + "type": "string", + "format": "date-time" + }, + "description": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "accommodations": "#/components/schemas/attributesInAccommodationResponse", + "excursions": "#/components/schemas/attributesInExcursionResponse", + "transports": "#/components/schemas/attributesInTransportResponse", + "vacations": "#/components/schemas/attributesInVacationResponse" + } + }, + "x-abstract": true + }, + "attributesInTransportResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/transportType" + } + ] + }, + "durationInMinutes": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateAccommodationRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "address": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateExcursionRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "occursAt": { + "type": "string", + "format": "date-time" + }, + "description": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "accommodations": "#/components/schemas/attributesInUpdateAccommodationRequest", + "excursions": "#/components/schemas/attributesInUpdateExcursionRequest", + "transports": "#/components/schemas/attributesInUpdateTransportRequest", + "vacations": "#/components/schemas/attributesInUpdateVacationRequest" + } + }, + "x-abstract": true + }, + "attributesInUpdateTransportRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/transportType" + } + ] + }, + "durationInMinutes": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateVacationRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "startsAt": { + "type": "string", + "format": "date-time" + }, + "endsAt": { + "type": "string", + "format": "date-time" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInVacationResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "startsAt": { + "type": "string", + "format": "date-time" + }, + "endsAt": { + "type": "string", + "format": "date-time" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createAccommodationRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateAccommodationRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "createExcursionRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateExcursionRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "createTransportRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateTransportRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "createVacationRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateVacationRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "dataInAccommodationResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInAccommodationResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateAccommodationRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateAccommodationRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateExcursionRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateExcursionRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateTransportRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateTransportRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateVacationRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateVacationRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateVacationRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInExcursionResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInExcursionResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInTransportResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInTransportResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateAccommodationRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateAccommodationRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateExcursionRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateExcursionRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateTransportRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateTransportRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateVacationRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateVacationRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateVacationRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInVacationResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInVacationResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInVacationResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "errorLinks": { + "type": "object", + "properties": { + "about": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorObject": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorLinks" + } + ], + "nullable": true + }, + "status": { + "type": "string" + }, + "code": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/errorSource" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorResponseDocument": { + "required": [ + "errors", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorTopLevelLinks" + } + ] + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/errorObject" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorSource": { + "type": "object", + "properties": { + "pointer": { + "type": "string", + "nullable": true + }, + "parameter": { + "type": "string", + "nullable": true + }, + "header": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "excursionCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInExcursionResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "excursionIdentifierCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/excursionIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "excursionIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "excursionIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/excursionResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "excursionResourceType": { + "enum": [ + "excursions" + ], + "type": "string" + }, + "identifierInRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "accommodations": "#/components/schemas/accommodationIdentifierInRequest", + "excursions": "#/components/schemas/excursionIdentifierInRequest", + "transports": "#/components/schemas/transportIdentifierInRequest" + } + }, + "x-abstract": true + }, + "meta": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "nullableSecondaryTransportResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInTransportResponse" + } + ], + "nullable": true + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableToOneTransportInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/transportIdentifierInRequest" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableToOneTransportInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/transportIdentifierInResponse" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableTransportIdentifierResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/transportIdentifierInResponse" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryAccommodationResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInAccommodationResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryExcursionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInExcursionResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryTransportResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInTransportResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryVacationResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInVacationResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "relationshipLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + } + }, + "additionalProperties": false + }, + "relationshipsInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "vacations": "#/components/schemas/relationshipsInCreateVacationRequest" + } + }, + "x-abstract": true + }, + "relationshipsInCreateVacationRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "required": [ + "accommodation" + ], + "type": "object", + "properties": { + "accommodation": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneAccommodationInRequest" + } + ] + }, + "transport": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneTransportInRequest" + } + ] + }, + "excursions": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyExcursionInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "vacations": "#/components/schemas/relationshipsInVacationResponse" + } + }, + "x-abstract": true + }, + "relationshipsInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "vacations": "#/components/schemas/relationshipsInUpdateVacationRequest" + } + }, + "x-abstract": true + }, + "relationshipsInUpdateVacationRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "accommodation": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneAccommodationInRequest" + } + ] + }, + "transport": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneTransportInRequest" + } + ] + }, + "excursions": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyExcursionInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInVacationResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "type": "object", + "properties": { + "accommodation": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneAccommodationInResponse" + } + ] + }, + "transport": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneTransportInResponse" + } + ] + }, + "excursions": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyExcursionInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "resourceCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceIdentifierCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceIdentifierTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceInCreateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "accommodations": "#/components/schemas/dataInCreateAccommodationRequest", + "excursions": "#/components/schemas/dataInCreateExcursionRequest", + "transports": "#/components/schemas/dataInCreateTransportRequest", + "vacations": "#/components/schemas/dataInCreateVacationRequest" + } + }, + "x-abstract": true + }, + "resourceInResponse": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "accommodations": "#/components/schemas/dataInAccommodationResponse", + "excursions": "#/components/schemas/dataInExcursionResponse", + "transports": "#/components/schemas/dataInTransportResponse", + "vacations": "#/components/schemas/dataInVacationResponse" + } + }, + "x-abstract": true + }, + "resourceInUpdateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "accommodations": "#/components/schemas/dataInUpdateAccommodationRequest", + "excursions": "#/components/schemas/dataInUpdateExcursionRequest", + "transports": "#/components/schemas/dataInUpdateTransportRequest", + "vacations": "#/components/schemas/dataInUpdateVacationRequest" + } + }, + "x-abstract": true + }, + "resourceLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceType": { + "enum": [ + "accommodations", + "excursions", + "transports", + "vacations" + ], + "type": "string" + }, + "secondaryAccommodationResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInAccommodationResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyExcursionInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/excursionIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyExcursionInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/excursionIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneAccommodationInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/accommodationIdentifierInRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneAccommodationInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/accommodationIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "transportCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInTransportResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "transportIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "transportIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/transportResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "transportResourceType": { + "enum": [ + "transports" + ], + "type": "string" + }, + "transportType": { + "enum": [ + 0, + 1, + 2, + 3 + ], + "type": "integer", + "format": "int32" + }, + "updateAccommodationRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateAccommodationRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateExcursionRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateExcursionRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateTransportRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateTransportRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateVacationRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateVacationRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "vacationCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInVacationResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/test/OpenApiTests/Links/Enabled/LinksEnabledTests.cs b/test/OpenApiTests/Links/Enabled/LinksEnabledTests.cs new file mode 100644 index 0000000000..ba476b5756 --- /dev/null +++ b/test/OpenApiTests/Links/Enabled/LinksEnabledTests.cs @@ -0,0 +1,113 @@ +using System.Text.Json; +using FluentAssertions; +using JsonApiDotNetCore.Resources.Annotations; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.Links.Enabled; + +public sealed class LinksEnabledTests : IClassFixture, LinkDbContext>> +{ + private readonly OpenApiTestContext, LinkDbContext> _testContext; + + public LinksEnabledTests(OpenApiTestContext, LinkDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + + testContext.SetTestOutputHelper(testOutputHelper); + testContext.SwaggerDocumentOutputDirectory = $"{GetType().Namespace!.Replace('.', '/')}/GeneratedSwagger"; + } + + [Theory] + [InlineData("resourceTopLevelLinks", LinkTypes.Self | LinkTypes.DescribedBy)] + [InlineData("resourceCollectionTopLevelLinks", LinkTypes.Self | LinkTypes.DescribedBy | LinkTypes.Pagination)] + [InlineData("resourceIdentifierTopLevelLinks", LinkTypes.Self | LinkTypes.Related | LinkTypes.DescribedBy)] + [InlineData("resourceIdentifierCollectionTopLevelLinks", LinkTypes.Self | LinkTypes.Related | LinkTypes.DescribedBy | LinkTypes.Pagination)] + [InlineData("errorTopLevelLinks", LinkTypes.Self | LinkTypes.DescribedBy)] + [InlineData("relationshipLinks", LinkTypes.Self | LinkTypes.Related)] + [InlineData("resourceLinks", LinkTypes.Self)] + public async Task All_configurable_link_schemas_are_exposed(string schemaId, LinkTypes expected) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas").With(schemasElement => + { + schemasElement.Should().ContainPath(schemaId).With(linksElement => + { + linksElement.Should().NotContainPath("required"); + + linksElement.Should().ContainPath("properties").With(propertiesElement => + { + string[] propertyNamesExpected = expected.ToPropertyNames().ToArray(); + string[] linkPropertyNames = propertiesElement.EnumerateObject().Select(propertyElement => propertyElement.Name).ToArray(); + + linkPropertyNames.Should().BeEquivalentTo(propertyNamesExpected); + }); + }); + }); + } + + [Theory] + [InlineData("resourceTopLevelLinks", "primaryAccommodationResponseDocument", true)] + [InlineData("resourceTopLevelLinks", "secondaryAccommodationResponseDocument", true)] + [InlineData("resourceTopLevelLinks", "primaryExcursionResponseDocument", true)] + [InlineData("resourceTopLevelLinks", "primaryTransportResponseDocument", true)] + [InlineData("resourceTopLevelLinks", "nullableSecondaryTransportResponseDocument", true)] + [InlineData("resourceTopLevelLinks", "primaryVacationResponseDocument", true)] + [InlineData("resourceCollectionTopLevelLinks", "accommodationCollectionResponseDocument", true)] + [InlineData("resourceCollectionTopLevelLinks", "excursionCollectionResponseDocument", true)] + [InlineData("resourceCollectionTopLevelLinks", "transportCollectionResponseDocument", true)] + [InlineData("resourceCollectionTopLevelLinks", "vacationCollectionResponseDocument", true)] + [InlineData("resourceIdentifierTopLevelLinks", "accommodationIdentifierResponseDocument", true)] + [InlineData("resourceIdentifierTopLevelLinks", "nullableTransportIdentifierResponseDocument", true)] + [InlineData("resourceIdentifierCollectionTopLevelLinks", "excursionIdentifierCollectionResponseDocument", true)] + [InlineData("errorTopLevelLinks", "errorResponseDocument", true)] + [InlineData("relationshipLinks", "toOneAccommodationInResponse", false)] + [InlineData("relationshipLinks", "toManyExcursionInResponse", false)] + [InlineData("relationshipLinks", "nullableToOneTransportInResponse", false)] + [InlineData("resourceLinks", "dataInAccommodationResponse.allOf[1]", false)] + [InlineData("resourceLinks", "dataInExcursionResponse.allOf[1]", false)] + [InlineData("resourceLinks", "dataInTransportResponse.allOf[1]", false)] + [InlineData("resourceLinks", "dataInVacationResponse.allOf[1]", false)] + public async Task All_container_schemas_contain_correct_link_property(string linkSchemaId, string containerSchemaId, bool isRequired) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas").With(schemasElement => + { + schemasElement.Should().ContainPath(containerSchemaId).With(containerElement => + { + if (isRequired) + { + containerElement.Should().ContainPath("required").With(requiredElement => + { + requiredElement.Should().ContainArrayElement("links"); + }); + } + else + { + if (containerElement.TryGetProperty("required", out JsonElement requiredElement)) + { + requiredElement.Should().NotContainArrayElement("links"); + } + else + { + containerElement.Should().NotContainPath("required"); + } + } + + containerElement.Should().ContainPath("properties.links.allOf[0].$ref").ShouldBeSchemaReferenceId(linkSchemaId); + }); + }); + } +} diff --git a/test/OpenApiTests/Links/Excursion.cs b/test/OpenApiTests/Links/Excursion.cs new file mode 100644 index 0000000000..92143cab73 --- /dev/null +++ b/test/OpenApiTests/Links/Excursion.cs @@ -0,0 +1,18 @@ +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.Links; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.Links")] +public sealed class Excursion : Identifiable +{ + [Attr] + [Required] + public DateTime? OccursAt { get; set; } + + [Attr] + public string Description { get; set; } = null!; +} diff --git a/test/OpenApiTests/Links/LinkDbContext.cs b/test/OpenApiTests/Links/LinkDbContext.cs new file mode 100644 index 0000000000..c12d04c0c0 --- /dev/null +++ b/test/OpenApiTests/Links/LinkDbContext.cs @@ -0,0 +1,15 @@ +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; +using TestBuildingBlocks; + +namespace OpenApiTests.Links; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public sealed class LinkDbContext(DbContextOptions options) + : TestableDbContext(options) +{ + public DbSet Vacations => Set(); + public DbSet Accommodations => Set(); + public DbSet Transports => Set(); + public DbSet Excursions => Set(); +} diff --git a/test/OpenApiTests/Links/LinkFakers.cs b/test/OpenApiTests/Links/LinkFakers.cs new file mode 100644 index 0000000000..92e4a093f0 --- /dev/null +++ b/test/OpenApiTests/Links/LinkFakers.cs @@ -0,0 +1,36 @@ +using Bogus; +using JetBrains.Annotations; +using TestBuildingBlocks; + +// @formatter:wrap_chained_method_calls chop_if_long +// @formatter:wrap_before_first_method_call true + +namespace OpenApiTests.Links; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public sealed class LinkFakers +{ + private readonly Lazy> _lazyVacationFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(vacation => vacation.StartsAt, faker => faker.Date.Future()) + .RuleFor(vacation => vacation.EndsAt, faker => faker.Date.Future())); + + private readonly Lazy> _lazyAccommodationFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(accommodation => accommodation.Address, faker => faker.Address.FullAddress())); + + private readonly Lazy> _lazyTransportFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(transport => transport.Type, faker => faker.PickRandom()) + .RuleFor(transport => transport.DurationInMinutes, faker => faker.Random.Int(30, 24 * 60))); + + private readonly Lazy> _lazyExcursionFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(excursion => excursion.OccursAt, faker => faker.Date.Future()) + .RuleFor(excursion => excursion.Description, faker => faker.Lorem.Sentence())); + + public Faker Vacation => _lazyVacationFaker.Value; + public Faker Accommodation => _lazyAccommodationFaker.Value; + public Faker Transport => _lazyTransportFaker.Value; + public Faker Excursion => _lazyExcursionFaker.Value; +} diff --git a/test/OpenApiTests/Links/LinkTypesExtensions.cs b/test/OpenApiTests/Links/LinkTypesExtensions.cs new file mode 100644 index 0000000000..192590b692 --- /dev/null +++ b/test/OpenApiTests/Links/LinkTypesExtensions.cs @@ -0,0 +1,32 @@ +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.Links; + +internal static class LinkTypesExtensions +{ + public static IEnumerable ToPropertyNames(this LinkTypes linkTypes) + { + if (linkTypes.HasFlag(LinkTypes.Self)) + { + yield return "self"; + } + + if (linkTypes.HasFlag(LinkTypes.Related)) + { + yield return "related"; + } + + if (linkTypes.HasFlag(LinkTypes.DescribedBy)) + { + yield return "describedby"; + } + + if (linkTypes.HasFlag(LinkTypes.Pagination)) + { + yield return "first"; + yield return "last"; + yield return "prev"; + yield return "next"; + } + } +} diff --git a/test/OpenApiTests/Links/Mixed/LinksMixedTests.cs b/test/OpenApiTests/Links/Mixed/LinksMixedTests.cs new file mode 100644 index 0000000000..3a6be9dc32 --- /dev/null +++ b/test/OpenApiTests/Links/Mixed/LinksMixedTests.cs @@ -0,0 +1,96 @@ +using System.Text.Json; +using FluentAssertions; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Resources.Annotations; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.Links.Mixed; + +public sealed class LinksMixedTests : IClassFixture, LinkDbContext>> +{ + private readonly OpenApiTestContext, LinkDbContext> _testContext; + + public LinksMixedTests(OpenApiTestContext, LinkDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + + testContext.SetTestOutputHelper(testOutputHelper); + testContext.ConfigureServices(services => services.AddSingleton(CreateResourceGraph)); + + var options = (JsonApiOptions)testContext.Factory.Services.GetRequiredService(); + options.TopLevelLinks = LinkTypes.Pagination; + options.ResourceLinks = LinkTypes.NotConfigured; + options.RelationshipLinks = LinkTypes.None; + } + + [Theory] + [InlineData("resourceTopLevelLinks", LinkTypes.Self)] + [InlineData("resourceCollectionTopLevelLinks", LinkTypes.Self)] + [InlineData("resourceIdentifierTopLevelLinks", LinkTypes.Self | LinkTypes.Related)] + [InlineData("resourceIdentifierCollectionTopLevelLinks", LinkTypes.Self | LinkTypes.Related)] + [InlineData("errorTopLevelLinks", LinkTypes.Self)] + [InlineData("relationshipLinks", LinkTypes.Self | LinkTypes.Related)] + [InlineData("resourceLinks", LinkTypes.Self)] + public async Task Expected_configurable_link_schemas_are_exposed(string schemaId, LinkTypes expected) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas").With(schemasElement => + { + schemasElement.Should().ContainPath(schemaId).With(linksElement => + { + linksElement.Should().NotContainPath("required"); + + linksElement.Should().ContainPath("properties").With(propertiesElement => + { + string[] propertyNamesExpected = expected.ToPropertyNames().ToArray(); + string[] linkPropertyNames = propertiesElement.EnumerateObject().Select(propertyElement => propertyElement.Name).ToArray(); + + linkPropertyNames.Should().BeEquivalentTo(propertyNamesExpected); + }); + }); + }); + } + + private static IResourceGraph CreateResourceGraph(IServiceProvider serviceProvider) + { + ResourceGraphBuilder builder = CreateResourceGraphBuilder(serviceProvider); + var editor = new ResourceGraphEditor(builder); + + editor.ChangeLinksInResourceType(typeof(Vacation), LinkTypes.None, null, null); + editor.ChangeLinkInRelationship(typeof(Vacation), nameof(Vacation.Transport), LinkTypes.Related); + + editor.ChangeLinksInResourceType(typeof(Accommodation), LinkTypes.Self, LinkTypes.Self, null); + + editor.ChangeLinksInResourceType(typeof(Transport), LinkTypes.Related, LinkTypes.Self, LinkTypes.Self); + + editor.ChangeLinksInResourceType(typeof(Excursion), LinkTypes.None, null, LinkTypes.None); + + return editor.GetResourceGraph(); + } + + private static ResourceGraphBuilder CreateResourceGraphBuilder(IServiceProvider serviceProvider) + { + var options = serviceProvider.GetRequiredService(); + var loggerFactory = serviceProvider.GetRequiredService(); + + using IServiceScope scope = serviceProvider.CreateScope(); + var dbContext = scope.ServiceProvider.GetRequiredService(); + + var builder = new ResourceGraphBuilder(options, loggerFactory); + builder.Add(dbContext); + + return builder; + } +} diff --git a/test/OpenApiTests/Links/Mixed/ResourceGraphEditor.cs b/test/OpenApiTests/Links/Mixed/ResourceGraphEditor.cs new file mode 100644 index 0000000000..5a2f19cfa7 --- /dev/null +++ b/test/OpenApiTests/Links/Mixed/ResourceGraphEditor.cs @@ -0,0 +1,41 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.Links.Mixed; + +/// +/// Enables changing declared links on resource types and relationships, so the model does not need to be duplicated for testing. +/// +internal sealed class ResourceGraphEditor +{ + private readonly Dictionary _resourceTypesByClrTypeName; + + public ResourceGraphEditor(ResourceGraphBuilder builder) + { + IResourceGraph resourceGraph = builder.Build(); + _resourceTypesByClrTypeName = resourceGraph.GetResourceTypes().ToDictionary(resourceType => resourceType.ClrType, resourceType => resourceType); + } + + public void ChangeLinksInResourceType(Type resourceClrType, LinkTypes? topLevelLinks, LinkTypes? resourceLinks, LinkTypes? relationshipLinks) + { + ResourceType resourceType = _resourceTypesByClrTypeName[resourceClrType]; + + _resourceTypesByClrTypeName[resourceClrType] = new ResourceType(resourceType.PublicName, resourceType.ClientIdGeneration, resourceType.ClrType, + resourceType.IdentityClrType, resourceType.Attributes, resourceType.Relationships, resourceType.EagerLoads, + topLevelLinks ?? resourceType.TopLevelLinks, resourceLinks ?? resourceType.ResourceLinks, relationshipLinks ?? resourceType.RelationshipLinks); + } + + public void ChangeLinkInRelationship(Type resourceClrType, string relationshipPropertyName, LinkTypes links) + { + ResourceType resourceType = _resourceTypesByClrTypeName[resourceClrType]; + + RelationshipAttribute relationship = resourceType.GetRelationshipByPropertyName(relationshipPropertyName); + relationship.Links = links; + } + + public IResourceGraph GetResourceGraph() + { + HashSet resourceTypeSet = _resourceTypesByClrTypeName.Values.ToHashSet(); + return new ResourceGraph(resourceTypeSet); + } +} diff --git a/test/OpenApiTests/Links/Transport.cs b/test/OpenApiTests/Links/Transport.cs new file mode 100644 index 0000000000..dda6021f0b --- /dev/null +++ b/test/OpenApiTests/Links/Transport.cs @@ -0,0 +1,19 @@ +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.Links; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.Links")] +public sealed class Transport : Identifiable +{ + [Attr] + [Required] + public TransportType? Type { get; set; } + + [Attr] + [Required] + public int? DurationInMinutes { get; set; } +} diff --git a/test/OpenApiTests/Links/TransportType.cs b/test/OpenApiTests/Links/TransportType.cs new file mode 100644 index 0000000000..6f1bbf9ea7 --- /dev/null +++ b/test/OpenApiTests/Links/TransportType.cs @@ -0,0 +1,12 @@ +using JetBrains.Annotations; + +namespace OpenApiTests.Links; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public enum TransportType +{ + Airplane, + Train, + Bus, + Boat +} diff --git a/test/OpenApiTests/Links/Vacation.cs b/test/OpenApiTests/Links/Vacation.cs new file mode 100644 index 0000000000..df592a4423 --- /dev/null +++ b/test/OpenApiTests/Links/Vacation.cs @@ -0,0 +1,28 @@ +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.Links; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.Links")] +public sealed class Vacation : Identifiable +{ + [Attr] + [Required] + public DateTime? StartsAt { get; set; } + + [Attr] + [Required] + public DateTime? EndsAt { get; set; } + + [HasOne] + public Accommodation Accommodation { get; set; } = null!; + + [HasOne] + public Transport? Transport { get; set; } + + [HasMany] + public ISet Excursions { get; set; } = new HashSet(); +} diff --git a/test/OpenApiTests/ModelStateValidation/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/ModelStateValidation/GeneratedSwagger/swagger.g.json new file mode 100644 index 0000000000..05a83c87ee --- /dev/null +++ b/test/OpenApiTests/ModelStateValidation/GeneratedSwagger/swagger.g.json @@ -0,0 +1,1064 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "OpenApiTests", + "version": "1.0" + }, + "servers": [ + { + "url": "http://localhost" + } + ], + "paths": { + "/socialMediaAccounts": { + "post": { + "tags": [ + "socialMediaAccounts" + ], + "summary": "Creates a new socialMediaAccount.", + "operationId": "postSocialMediaAccount", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the socialMediaAccount to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createSocialMediaAccountRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The socialMediaAccount was successfully created, which resulted in additional changes. The newly created socialMediaAccount is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created socialMediaAccount can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primarySocialMediaAccountResponseDocument" + } + } + } + }, + "204": { + "description": "The socialMediaAccount was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/socialMediaAccounts/{id}": { + "patch": { + "tags": [ + "socialMediaAccounts" + ], + "summary": "Updates an existing socialMediaAccount.", + "operationId": "patchSocialMediaAccount", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the socialMediaAccount to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the socialMediaAccount to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateSocialMediaAccountRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The socialMediaAccount was successfully updated, which resulted in additional changes. The updated socialMediaAccount is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primarySocialMediaAccountResponseDocument" + } + } + } + }, + "204": { + "description": "The socialMediaAccount was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The socialMediaAccount or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "attributesInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "socialMediaAccounts": "#/components/schemas/attributesInCreateSocialMediaAccountRequest" + } + }, + "x-abstract": true + }, + "attributesInCreateSocialMediaAccountRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "lastName" + ], + "type": "object", + "properties": { + "alternativeId": { + "type": "string", + "format": "uuid", + "nullable": true + }, + "firstName": { + "maxLength": 20, + "minLength": 2, + "type": "string", + "nullable": true + }, + "lastName": { + "type": "string" + }, + "userName": { + "maxLength": 18, + "minLength": 3, + "pattern": "^[a-zA-Z]+$", + "type": "string", + "nullable": true + }, + "creditCard": { + "type": "string", + "format": "credit-card", + "nullable": true + }, + "email": { + "type": "string", + "format": "email", + "nullable": true + }, + "password": { + "maxLength": 60, + "minLength": 20, + "type": "string", + "format": "byte", + "nullable": true + }, + "phone": { + "type": "string", + "format": "tel", + "nullable": true + }, + "age": { + "maximum": 122.9, + "exclusiveMaximum": true, + "minimum": 0.1, + "exclusiveMinimum": true, + "type": "number", + "format": "double", + "nullable": true + }, + "profilePicture": { + "type": "string", + "format": "uri", + "nullable": true + }, + "backgroundPicture": { + "type": "string", + "format": "uri", + "nullable": true + }, + "tags": { + "maxItems": 10, + "minItems": 1, + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + }, + "countryCode": { + "type": "string", + "nullable": true + }, + "planet": { + "type": "string", + "nullable": true + }, + "nextRevalidation": { + "type": "string", + "format": "date-span", + "nullable": true + }, + "validatedAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "validatedAtDate": { + "type": "string", + "format": "date", + "nullable": true + }, + "validatedAtTime": { + "type": "string", + "format": "time", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "socialMediaAccounts": "#/components/schemas/attributesInSocialMediaAccountResponse" + } + }, + "x-abstract": true + }, + "attributesInSocialMediaAccountResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "alternativeId": { + "type": "string", + "format": "uuid", + "nullable": true + }, + "firstName": { + "maxLength": 20, + "minLength": 2, + "type": "string", + "nullable": true + }, + "lastName": { + "type": "string" + }, + "userName": { + "maxLength": 18, + "minLength": 3, + "pattern": "^[a-zA-Z]+$", + "type": "string", + "nullable": true + }, + "creditCard": { + "type": "string", + "format": "credit-card", + "nullable": true + }, + "email": { + "type": "string", + "format": "email", + "nullable": true + }, + "password": { + "maxLength": 60, + "minLength": 20, + "type": "string", + "format": "byte", + "nullable": true + }, + "phone": { + "type": "string", + "format": "tel", + "nullable": true + }, + "age": { + "maximum": 122.9, + "exclusiveMaximum": true, + "minimum": 0.1, + "exclusiveMinimum": true, + "type": "number", + "format": "double", + "nullable": true + }, + "profilePicture": { + "type": "string", + "format": "uri", + "nullable": true + }, + "backgroundPicture": { + "type": "string", + "format": "uri", + "nullable": true + }, + "tags": { + "maxItems": 10, + "minItems": 1, + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + }, + "countryCode": { + "type": "string", + "nullable": true + }, + "planet": { + "type": "string", + "nullable": true + }, + "nextRevalidation": { + "type": "string", + "format": "date-span", + "nullable": true + }, + "validatedAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "validatedAtDate": { + "type": "string", + "format": "date", + "nullable": true + }, + "validatedAtTime": { + "type": "string", + "format": "time", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "socialMediaAccounts": "#/components/schemas/attributesInUpdateSocialMediaAccountRequest" + } + }, + "x-abstract": true + }, + "attributesInUpdateSocialMediaAccountRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "alternativeId": { + "type": "string", + "format": "uuid", + "nullable": true + }, + "firstName": { + "maxLength": 20, + "minLength": 2, + "type": "string", + "nullable": true + }, + "lastName": { + "type": "string" + }, + "userName": { + "maxLength": 18, + "minLength": 3, + "pattern": "^[a-zA-Z]+$", + "type": "string", + "nullable": true + }, + "creditCard": { + "type": "string", + "format": "credit-card", + "nullable": true + }, + "email": { + "type": "string", + "format": "email", + "nullable": true + }, + "password": { + "maxLength": 60, + "minLength": 20, + "type": "string", + "format": "byte", + "nullable": true + }, + "phone": { + "type": "string", + "format": "tel", + "nullable": true + }, + "age": { + "maximum": 122.9, + "exclusiveMaximum": true, + "minimum": 0.1, + "exclusiveMinimum": true, + "type": "number", + "format": "double", + "nullable": true + }, + "profilePicture": { + "type": "string", + "format": "uri", + "nullable": true + }, + "backgroundPicture": { + "type": "string", + "format": "uri", + "nullable": true + }, + "tags": { + "maxItems": 10, + "minItems": 1, + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + }, + "countryCode": { + "type": "string", + "nullable": true + }, + "planet": { + "type": "string", + "nullable": true + }, + "nextRevalidation": { + "type": "string", + "format": "date-span", + "nullable": true + }, + "validatedAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "validatedAtDate": { + "type": "string", + "format": "date", + "nullable": true + }, + "validatedAtTime": { + "type": "string", + "format": "time", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createSocialMediaAccountRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateSocialMediaAccountRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "dataInCreateSocialMediaAccountRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateSocialMediaAccountRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInSocialMediaAccountResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInSocialMediaAccountResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateSocialMediaAccountRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateSocialMediaAccountRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "errorLinks": { + "type": "object", + "properties": { + "about": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorObject": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorLinks" + } + ], + "nullable": true + }, + "status": { + "type": "string" + }, + "code": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/errorSource" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorResponseDocument": { + "required": [ + "errors", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorTopLevelLinks" + } + ] + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/errorObject" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorSource": { + "type": "object", + "properties": { + "pointer": { + "type": "string", + "nullable": true + }, + "parameter": { + "type": "string", + "nullable": true + }, + "header": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "meta": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "primarySocialMediaAccountResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInSocialMediaAccountResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "resourceInCreateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "socialMediaAccounts": "#/components/schemas/dataInCreateSocialMediaAccountRequest" + } + }, + "x-abstract": true + }, + "resourceInResponse": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "socialMediaAccounts": "#/components/schemas/dataInSocialMediaAccountResponse" + } + }, + "x-abstract": true + }, + "resourceInUpdateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "socialMediaAccounts": "#/components/schemas/dataInUpdateSocialMediaAccountRequest" + } + }, + "x-abstract": true + }, + "resourceLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceType": { + "enum": [ + "socialMediaAccounts" + ], + "type": "string" + }, + "updateSocialMediaAccountRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateSocialMediaAccountRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/test/OpenApiTests/ModelStateValidation/ModelStateValidationDbContext.cs b/test/OpenApiTests/ModelStateValidation/ModelStateValidationDbContext.cs new file mode 100644 index 0000000000..d8b681b3ea --- /dev/null +++ b/test/OpenApiTests/ModelStateValidation/ModelStateValidationDbContext.cs @@ -0,0 +1,12 @@ +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; +using TestBuildingBlocks; + +namespace OpenApiTests.ModelStateValidation; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public sealed class ModelStateValidationDbContext(DbContextOptions options) + : TestableDbContext(options) +{ + public DbSet SocialMediaAccounts => Set(); +} diff --git a/test/OpenApiTests/ModelStateValidation/ModelStateValidationFakers.cs b/test/OpenApiTests/ModelStateValidation/ModelStateValidationFakers.cs new file mode 100644 index 0000000000..1fdc2203da --- /dev/null +++ b/test/OpenApiTests/ModelStateValidation/ModelStateValidationFakers.cs @@ -0,0 +1,44 @@ +using Bogus; +using JetBrains.Annotations; +using TestBuildingBlocks; + +// @formatter:wrap_chained_method_calls chop_if_long +// @formatter:wrap_before_first_method_call true + +namespace OpenApiTests.ModelStateValidation; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public sealed class ModelStateValidationFakers +{ + private readonly Lazy> _lazySocialMediaAccountFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(socialMediaAccount => socialMediaAccount.AlternativeId, faker => faker.Random.Guid()) + .RuleFor(socialMediaAccount => socialMediaAccount.FirstName, faker => faker.Person.FirstName) + .RuleFor(socialMediaAccount => socialMediaAccount.LastName, faker => faker.Person.LastName) + .RuleFor(socialMediaAccount => socialMediaAccount.UserName, faker => faker.Random.String2(3, 18)) + .RuleFor(socialMediaAccount => socialMediaAccount.CreditCard, faker => faker.Finance.CreditCardNumber()) + .RuleFor(socialMediaAccount => socialMediaAccount.Email, faker => faker.Person.Email) + .RuleFor(socialMediaAccount => socialMediaAccount.Password, faker => + { + int byteCount = faker.Random.Number(ModelStateValidation.SocialMediaAccount.MinPasswordChars, + ModelStateValidation.SocialMediaAccount.MaxPasswordChars); + + return Convert.ToBase64String(faker.Random.Bytes(byteCount)); + }) + .RuleFor(socialMediaAccount => socialMediaAccount.Phone, faker => faker.Person.Phone) + .RuleFor(socialMediaAccount => socialMediaAccount.Age, faker => faker.Random.Double(0.1, 122.9)) + .RuleFor(socialMediaAccount => socialMediaAccount.ProfilePicture, faker => new Uri(faker.Image.LoremFlickrUrl())) + .RuleFor(socialMediaAccount => socialMediaAccount.BackgroundPicture, faker => faker.Image.LoremFlickrUrl()) + .RuleFor(socialMediaAccount => socialMediaAccount.Tags, faker => faker.Make(faker.Random.Number(1, 10), () => faker.Random.Word())) + .RuleFor(socialMediaAccount => socialMediaAccount.CountryCode, faker => faker.Random.ListItem([ + "NL", + "FR" + ])) + .RuleFor(socialMediaAccount => socialMediaAccount.Planet, faker => faker.Random.Word()) + .RuleFor(socialMediaAccount => socialMediaAccount.NextRevalidation, faker => TimeSpan.FromHours(faker.Random.Number(1, 5))) + .RuleFor(socialMediaAccount => socialMediaAccount.ValidatedAt, faker => faker.Date.Recent().ToUniversalTime().TruncateToWholeMilliseconds()) + .RuleFor(socialMediaAccount => socialMediaAccount.ValidatedAtDate, faker => DateOnly.FromDateTime(faker.Date.Recent())) + .RuleFor(socialMediaAccount => socialMediaAccount.ValidatedAtTime, faker => TimeOnly.FromDateTime(faker.Date.Recent().TruncateToWholeMilliseconds()))); + + public Faker SocialMediaAccount => _lazySocialMediaAccountFaker.Value; +} diff --git a/test/OpenApiTests/ModelStateValidation/ModelStateValidationTests.cs b/test/OpenApiTests/ModelStateValidation/ModelStateValidationTests.cs new file mode 100644 index 0000000000..3040cb6a26 --- /dev/null +++ b/test/OpenApiTests/ModelStateValidation/ModelStateValidationTests.cs @@ -0,0 +1,299 @@ +using System.Text.Json; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.ModelStateValidation; + +public sealed class ModelStateValidationTests : IClassFixture, ModelStateValidationDbContext>> +{ + // ReSharper disable once UseCollectionExpression (https://youtrack.jetbrains.com/issue/RSRP-497450) + public static readonly TheoryData SchemaNames = new() + { + "attributesInCreateSocialMediaAccountRequest", + "attributesInUpdateSocialMediaAccountRequest", + "attributesInSocialMediaAccountResponse" + }; + + private readonly OpenApiTestContext, ModelStateValidationDbContext> _testContext; + + public ModelStateValidationTests(OpenApiTestContext, ModelStateValidationDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + + testContext.UseController(); + + testContext.SetTestOutputHelper(testOutputHelper); + testContext.SwaggerDocumentOutputDirectory = $"{GetType().Namespace!.Replace('.', '/')}/GeneratedSwagger"; + } + + [Theory] + [MemberData(nameof(SchemaNames))] + public async Task Guid_type_produces_expected_schema(string modelName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath($"components.schemas.{modelName}.allOf[1].properties.alternativeId").With(alternativeIdElement => + { + alternativeIdElement.Should().HaveProperty("type", "string"); + alternativeIdElement.Should().HaveProperty("format", "uuid"); + }); + } + + [Theory] + [MemberData(nameof(SchemaNames))] + public async Task Length_annotation_on_resource_string_property_produces_expected_schema(string modelName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath($"components.schemas.{modelName}.allOf[1].properties.firstName").With(firstNameElement => + { + firstNameElement.Should().HaveProperty("type", "string"); + firstNameElement.Should().HaveProperty("maxLength", 20); + firstNameElement.Should().HaveProperty("minLength", 2); + }); + } + + [Theory] + [MemberData(nameof(SchemaNames))] + public async Task Required_annotation_with_AllowEmptyStrings_on_resource_property_produces_expected_schema(string modelName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath($"components.schemas.{modelName}.allOf[1].properties.lastName").With(lastNameElement => + { + lastNameElement.Should().HaveProperty("type", "string"); + lastNameElement.Should().NotContainPath("minLength"); + }); + } + + [Theory] + [MemberData(nameof(SchemaNames))] + public async Task StringLength_annotation_on_resource_property_produces_expected_schema(string modelName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath($"components.schemas.{modelName}.allOf[1].properties.userName").With(userNameElement => + { + userNameElement.Should().HaveProperty("type", "string"); + userNameElement.Should().HaveProperty("maxLength", 18); + userNameElement.Should().HaveProperty("minLength", 3); + }); + } + + [Theory] + [MemberData(nameof(SchemaNames))] + public async Task RegularExpression_annotation_on_resource_property_produces_expected_schema(string modelName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath($"components.schemas.{modelName}.allOf[1].properties.userName").With(userNameElement => + { + userNameElement.Should().HaveProperty("type", "string"); + userNameElement.Should().HaveProperty("pattern", "^[a-zA-Z]+$"); + }); + } + + [Theory] + [MemberData(nameof(SchemaNames))] + public async Task CreditCard_annotation_on_resource_property_produces_expected_schema(string modelName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath($"components.schemas.{modelName}.allOf[1].properties.creditCard").With(creditCardElement => + { + creditCardElement.Should().HaveProperty("type", "string"); + creditCardElement.Should().HaveProperty("format", "credit-card"); + }); + } + + [Theory] + [MemberData(nameof(SchemaNames))] + public async Task Email_annotation_on_resource_property_produces_expected_schema(string modelName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath($"components.schemas.{modelName}.allOf[1].properties.email").With(emailElement => + { + emailElement.Should().HaveProperty("type", "string"); + emailElement.Should().HaveProperty("format", "email"); + }); + } + + [Theory] + [MemberData(nameof(SchemaNames))] + public async Task Min_max_length_annotation_on_resource_property_produces_expected_schema(string modelName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath($"components.schemas.{modelName}.allOf[1].properties.password").With(passwordElement => + { + passwordElement.Should().HaveProperty("type", "string"); + passwordElement.Should().HaveProperty("format", "byte"); + passwordElement.Should().HaveProperty("maxLength", SocialMediaAccount.MaxPasswordCharsInBase64); + passwordElement.Should().HaveProperty("minLength", SocialMediaAccount.MinPasswordCharsInBase64); + }); + } + + [Theory] + [MemberData(nameof(SchemaNames))] + public async Task Phone_annotation_on_resource_property_produces_expected_schema(string modelName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath($"components.schemas.{modelName}.allOf[1].properties.phone").With(phoneElement => + { + phoneElement.Should().HaveProperty("type", "string"); + phoneElement.Should().HaveProperty("format", "tel"); + }); + } + + [Theory] + [MemberData(nameof(SchemaNames))] + public async Task Range_annotation_on_resource_property_produces_expected_schema(string modelName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath($"components.schemas.{modelName}.allOf[1].properties.age").With(ageElement => + { + ageElement.Should().HaveProperty("type", "number"); + ageElement.Should().HaveProperty("format", "double"); + ageElement.Should().HaveProperty("maximum", 122.9); + ageElement.Should().HaveProperty("minimum", 0.1); + ageElement.Should().ContainPath("exclusiveMaximum").With(exclusiveElement => exclusiveElement.Should().Be(true)); + ageElement.Should().ContainPath("exclusiveMinimum").With(exclusiveElement => exclusiveElement.Should().Be(true)); + }); + } + + [Theory] + [MemberData(nameof(SchemaNames))] + public async Task Url_annotation_on_resource_property_produces_expected_schema(string modelName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath($"components.schemas.{modelName}.allOf[1].properties.profilePicture").With(profilePictureElement => + { + profilePictureElement.Should().HaveProperty("type", "string"); + profilePictureElement.Should().HaveProperty("format", "uri"); + }); + } + + [Theory] + [MemberData(nameof(SchemaNames))] + public async Task Uri_type_produces_expected_schema(string modelName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath($"components.schemas.{modelName}.allOf[1].properties.backgroundPicture").With(backgroundPictureElement => + { + backgroundPictureElement.Should().HaveProperty("type", "string"); + backgroundPictureElement.Should().HaveProperty("format", "uri"); + }); + } + + [Theory] + [MemberData(nameof(SchemaNames))] + public async Task Length_annotation_on_resource_list_property_produces_expected_schema(string modelName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath($"components.schemas.{modelName}.allOf[1].properties.tags").With(tagsElement => + { + tagsElement.Should().HaveProperty("type", "array"); + tagsElement.Should().HaveProperty("maxItems", 10); + tagsElement.Should().HaveProperty("minItems", 1); + + tagsElement.Should().ContainPath("items").With(itemsElement => + { + itemsElement.Should().HaveProperty("type", "string"); + }); + }); + } + + [Theory] + [MemberData(nameof(SchemaNames))] + public async Task TimeSpan_range_annotation_on_resource_property_produces_expected_schema(string modelName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath($"components.schemas.{modelName}.allOf[1].properties.nextRevalidation").With(nextRevalidationElement => + { + nextRevalidationElement.Should().HaveProperty("type", "string"); + nextRevalidationElement.Should().HaveProperty("format", "date-span"); + }); + } + + [Theory] + [MemberData(nameof(SchemaNames))] + public async Task DateTime_type_produces_expected_schema(string modelName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath($"components.schemas.{modelName}.allOf[1].properties.validatedAt").With(validatedAtElement => + { + validatedAtElement.Should().HaveProperty("type", "string"); + validatedAtElement.Should().HaveProperty("format", "date-time"); + }); + } + + [Theory] + [MemberData(nameof(SchemaNames))] + public async Task DateOnly_type_produces_expected_schema(string modelName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath($"components.schemas.{modelName}.allOf[1].properties.validatedAtDate").With(validatedDateAtElement => + { + validatedDateAtElement.Should().HaveProperty("type", "string"); + validatedDateAtElement.Should().HaveProperty("format", "date"); + }); + } + + [Theory] + [MemberData(nameof(SchemaNames))] + public async Task TimeOnly_type_produces_expected_schema(string modelName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath($"components.schemas.{modelName}.allOf[1].properties.validatedAtTime").With(validatedTimeAtElement => + { + validatedTimeAtElement.Should().HaveProperty("type", "string"); + validatedTimeAtElement.Should().HaveProperty("format", "time"); + }); + } +} diff --git a/test/OpenApiTests/ModelStateValidation/SocialMediaAccount.cs b/test/OpenApiTests/ModelStateValidation/SocialMediaAccount.cs new file mode 100644 index 0000000000..28fbd7148d --- /dev/null +++ b/test/OpenApiTests/ModelStateValidation/SocialMediaAccount.cs @@ -0,0 +1,88 @@ +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.ModelStateValidation; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.ModelStateValidation", GenerateControllerEndpoints = JsonApiEndpoints.Post | JsonApiEndpoints.Patch)] +public sealed class SocialMediaAccount : Identifiable +{ + public const int MinPasswordChars = 15; + public const int MinPasswordCharsInBase64 = (int)(4.0 / 3 * MinPasswordChars); + + public const int MaxPasswordChars = 45; + public const int MaxPasswordCharsInBase64 = (int)(4.0 / 3 * MaxPasswordChars); + + [Attr] + public Guid? AlternativeId { get; set; } + + [Attr] + [Length(2, 20)] + public string? FirstName { get; set; } + + [Attr] + [Required(AllowEmptyStrings = true)] + public string LastName { get; set; } = null!; + + [Attr] + [StringLength(18, MinimumLength = 3)] + [RegularExpression("^[a-zA-Z]+$", ErrorMessage = "Only letters are allowed.")] + public string? UserName { get; set; } + + [Attr] + [CreditCard] + public string? CreditCard { get; set; } + + [Attr] + [EmailAddress] + public string? Email { get; set; } + + [Attr] + [Base64String] + [MinLength(MinPasswordCharsInBase64)] + [MaxLength(MaxPasswordCharsInBase64)] + public string? Password { get; set; } + + [Attr] + [Phone] + public string? Phone { get; set; } + + [Attr] + [Range(0.1, 122.9, MinimumIsExclusive = true, MaximumIsExclusive = true)] + public double? Age { get; set; } + + [Attr] + public Uri? ProfilePicture { get; set; } + + [Attr] + [Url] + public string? BackgroundPicture { get; set; } + + [Attr] + [Length(1, 10)] + public List? Tags { get; set; } + + [Attr] + [AllowedValues(null, "NL", "FR")] + public string? CountryCode { get; set; } + + [Attr] + [DeniedValues("pluto")] + public string? Planet { get; set; } + + [Attr] + [Range(typeof(TimeSpan), "01:00", "05:00", ConvertValueInInvariantCulture = true)] + public TimeSpan? NextRevalidation { get; set; } + + [Attr] + public DateTime? ValidatedAt { get; set; } + + [Attr] + public DateOnly? ValidatedAtDate { get; set; } + + [Attr] + public TimeOnly? ValidatedAtTime { get; set; } +} diff --git a/test/OpenApiTests/NamingConventions/CamelCase/CamelCaseNamingConventionStartup.cs b/test/OpenApiTests/NamingConventions/CamelCase/CamelCaseNamingConventionStartup.cs new file mode 100644 index 0000000000..cf910b3a53 --- /dev/null +++ b/test/OpenApiTests/NamingConventions/CamelCase/CamelCaseNamingConventionStartup.cs @@ -0,0 +1,22 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.Configuration; +using TestBuildingBlocks; + +namespace OpenApiTests.NamingConventions.CamelCase; + +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +public sealed class CamelCaseNamingConventionStartup : OpenApiStartup + where TDbContext : TestableDbContext +{ + protected override void SetJsonApiOptions(JsonApiOptions options) + { + base.SetJsonApiOptions(options); + + options.IncludeJsonApiVersion = true; + options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; + options.SerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase; + options.SerializerOptions.Converters.Add(new JsonStringEnumConverter()); + } +} diff --git a/test/OpenApiTests/NamingConventions/CamelCase/CamelCaseTests.cs b/test/OpenApiTests/NamingConventions/CamelCase/CamelCaseTests.cs new file mode 100644 index 0000000000..ac102b673e --- /dev/null +++ b/test/OpenApiTests/NamingConventions/CamelCase/CamelCaseTests.cs @@ -0,0 +1,685 @@ +using System.Text.Json; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.NamingConventions.CamelCase; + +public sealed class CamelCaseTests : IClassFixture, NamingConventionDbContext>> +{ + private const string EscapedJsonApiMediaType = "['application/vnd.api+json; ext=openapi']"; + private const string EscapedOperationsMediaType = "['application/vnd.api+json; ext=atomic; ext=openapi']"; + + private readonly OpenApiTestContext, NamingConventionDbContext> _testContext; + + public CamelCaseTests(OpenApiTestContext, NamingConventionDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + + testContext.SetTestOutputHelper(testOutputHelper); + testContext.SwaggerDocumentOutputDirectory = $"{GetType().Namespace!.Replace('.', '/')}/GeneratedSwagger"; + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetCollection_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + string? documentSchemaRefId = null; + + document.Should().ContainPath("paths./supermarkets.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("getSupermarketCollection"); + }); + + documentSchemaRefId = getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("supermarketCollectionResponseDocument").SchemaReferenceId; + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + string? topLevelLinksSchemaRefId = null; + string? resourceDataSchemaRefId = null; + + schemasElement.Should().ContainPath($"{documentSchemaRefId}.properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("jsonapi.allOf[0].$ref").ShouldBeSchemaReferenceId("jsonapi"); + + topLevelLinksSchemaRefId = propertiesElement.Should().ContainPath("links.allOf[0].$ref") + .ShouldBeSchemaReferenceId("resourceCollectionTopLevelLinks").SchemaReferenceId; + + resourceDataSchemaRefId = propertiesElement.Should().ContainPath("data.items.$ref").ShouldBeSchemaReferenceId("dataInSupermarketResponse") + .SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{topLevelLinksSchemaRefId}.properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("self"); + propertiesElement.Should().ContainProperty("describedby"); + propertiesElement.Should().ContainProperty("first"); + propertiesElement.Should().ContainProperty("last"); + propertiesElement.Should().ContainProperty("prev"); + propertiesElement.Should().ContainProperty("next"); + }); + + string? resourceLinksSchemaRefId = null; + string? resourceAttributesInResponseSchemaRefId = null; + string? resourceRelationshipInResponseSchemaRefId = null; + + string abstractResourceDataSchemaRefId = schemasElement.Should().ContainPath($"{resourceDataSchemaRefId}.allOf[0].$ref") + .ShouldBeSchemaReferenceId("resourceInResponse").SchemaReferenceId; + + schemasElement.Should().ContainPath($"{abstractResourceDataSchemaRefId}.discriminator.mapping").With(mappingElement => + { + mappingElement.Should().ContainPath("supermarkets").ShouldBeSchemaReferenceId("dataInSupermarketResponse"); + mappingElement.Should().ContainPath("staffMembers").ShouldBeSchemaReferenceId("dataInStaffMemberResponse"); + }); + + schemasElement.Should().ContainPath($"{resourceDataSchemaRefId}.allOf[1].properties").With(propertiesElement => + { + resourceLinksSchemaRefId = propertiesElement.Should().ContainPath("links.allOf[0].$ref").ShouldBeSchemaReferenceId("resourceLinks") + .SchemaReferenceId; + + resourceAttributesInResponseSchemaRefId = propertiesElement.Should().ContainPath("attributes.allOf[0].$ref") + .ShouldBeSchemaReferenceId("attributesInSupermarketResponse").SchemaReferenceId; + + resourceRelationshipInResponseSchemaRefId = propertiesElement.Should().ContainPath("relationships.allOf[0].$ref") + .ShouldBeSchemaReferenceId("relationshipsInSupermarketResponse").SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{resourceLinksSchemaRefId}.properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("self"); + }); + + schemasElement.Should().ContainPath($"{resourceAttributesInResponseSchemaRefId}.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("nameOfCity"); + propertiesElement.Should().ContainProperty("kind"); + propertiesElement.Should().ContainPath("kind.allOf[0].$ref").ShouldBeSchemaReferenceId("supermarketType"); + }); + + string? nullableToOneResourceResponseDataSchemaRefId = null; + + schemasElement.Should().ContainPath($"{resourceRelationshipInResponseSchemaRefId}.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("storeManager"); + + propertiesElement.Should().ContainPath("storeManager.allOf[0].$ref").ShouldBeSchemaReferenceId("toOneStaffMemberInResponse"); + + nullableToOneResourceResponseDataSchemaRefId = propertiesElement.Should().ContainPath("backupStoreManager.allOf[0].$ref") + .ShouldBeSchemaReferenceId("nullableToOneStaffMemberInResponse").SchemaReferenceId; + + propertiesElement.Should().ContainProperty("cashiers"); + propertiesElement.Should().ContainPath("cashiers.allOf[0].$ref").ShouldBeSchemaReferenceId("toManyStaffMemberInResponse"); + }); + + string? relationshipLinksSchemaRefId = null; + string? relatedResourceIdentifierSchemaRefId = null; + + schemasElement.Should().ContainPath($"{nullableToOneResourceResponseDataSchemaRefId}.properties").With(propertiesElement => + { + relationshipLinksSchemaRefId = propertiesElement.Should().ContainPath("links.allOf[0].$ref").ShouldBeSchemaReferenceId("relationshipLinks") + .SchemaReferenceId; + + relatedResourceIdentifierSchemaRefId = propertiesElement.Should().ContainPath("data.allOf[0].$ref") + .ShouldBeSchemaReferenceId("staffMemberIdentifierInResponse").SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{relationshipLinksSchemaRefId}.properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("self"); + propertiesElement.Should().ContainProperty("related"); + }); + + string? relatedResourceTypeSchemaRefId = null; + + schemasElement.Should().ContainPath($"{relatedResourceIdentifierSchemaRefId}.properties").With(propertiesElement => + { + relatedResourceTypeSchemaRefId = propertiesElement.Should().ContainPath("type.allOf[0].$ref") + .ShouldBeSchemaReferenceId("staffMemberResourceType").SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{relatedResourceTypeSchemaRefId}.enum").With(codeElement => + { + codeElement.Should().ContainArrayElement("staffMembers"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetSingle_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + string? documentSchemaRefId = null; + + document.Should().ContainPath("paths./supermarkets/{id}.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("getSupermarket"); + }); + + documentSchemaRefId = getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("primarySupermarketResponseDocument").SchemaReferenceId; + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + string? topLevelLinksSchemaRefId = null; + + schemasElement.Should().ContainPath($"{documentSchemaRefId}.properties").With(propertiesElement => + { + topLevelLinksSchemaRefId = propertiesElement.Should().ContainPath("links.allOf[0].$ref").ShouldBeSchemaReferenceId("resourceTopLevelLinks") + .SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{topLevelLinksSchemaRefId}.properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("self"); + propertiesElement.Should().ContainProperty("describedby"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetSecondary_endpoint_with_single_resource() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + string? documentSchemaRefId = null; + + document.Should().ContainPath("paths./supermarkets/{id}/storeManager.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("getSupermarketStoreManager"); + }); + + documentSchemaRefId = getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("secondaryStaffMemberResponseDocument").SchemaReferenceId; + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + string? resourceDataSchemaRefId = null; + + schemasElement.Should().ContainPath($"{documentSchemaRefId}.properties").With(propertiesElement => + { + resourceDataSchemaRefId = propertiesElement.Should().ContainPath("data.allOf[0].$ref").ShouldBeSchemaReferenceId("dataInStaffMemberResponse") + .SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{resourceDataSchemaRefId}.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("attributes.allOf[0].$ref").ShouldBeSchemaReferenceId("attributesInStaffMemberResponse"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetSecondary_endpoint_with_nullable_resource() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./supermarkets/{id}/backupStoreManager.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("getSupermarketBackupStoreManager"); + }); + + getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("nullableSecondaryStaffMemberResponseDocument"); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetSecondary_endpoint_with_resources() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./supermarkets/{id}/cashiers.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("getSupermarketCashiers"); + }); + + getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("staffMemberCollectionResponseDocument"); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetRelationship_endpoint_with_ToOne_relationship() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + string? documentSchemaRefId = null; + + document.Should().ContainPath("paths./supermarkets/{id}/relationships/storeManager.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("getSupermarketStoreManagerRelationship"); + }); + + documentSchemaRefId = getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("staffMemberIdentifierResponseDocument").SchemaReferenceId; + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + string? topLevelLinksSchemaRefId = null; + + schemasElement.Should().ContainPath($"{documentSchemaRefId}.properties").With(propertiesElement => + { + topLevelLinksSchemaRefId = propertiesElement.Should().ContainPath("links.allOf[0].$ref") + .ShouldBeSchemaReferenceId("resourceIdentifierTopLevelLinks").SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{topLevelLinksSchemaRefId}.properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("self"); + propertiesElement.Should().ContainProperty("describedby"); + propertiesElement.Should().ContainProperty("related"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetRelationship_endpoint_with_nullable_ToOne_relationship() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./supermarkets/{id}/relationships/backupStoreManager.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("getSupermarketBackupStoreManagerRelationship"); + }); + + getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("nullableStaffMemberIdentifierResponseDocument"); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetRelationship_endpoint_with_ToMany_relationship() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + string? documentSchemaRefId = null; + + document.Should().ContainPath("paths./supermarkets/{id}/relationships/cashiers.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("getSupermarketCashiersRelationship"); + }); + + documentSchemaRefId = getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("staffMemberIdentifierCollectionResponseDocument").SchemaReferenceId; + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + string? topLevelLinksSchemaRefId = null; + + schemasElement.Should().ContainPath($"{documentSchemaRefId}.properties").With(propertiesElement => + { + topLevelLinksSchemaRefId = propertiesElement.Should().ContainPath("links.allOf[0].$ref") + .ShouldBeSchemaReferenceId("resourceIdentifierCollectionTopLevelLinks").SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{topLevelLinksSchemaRefId}.properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("self"); + propertiesElement.Should().ContainProperty("describedby"); + propertiesElement.Should().ContainProperty("related"); + propertiesElement.Should().ContainProperty("first"); + propertiesElement.Should().ContainProperty("last"); + propertiesElement.Should().ContainProperty("prev"); + propertiesElement.Should().ContainProperty("next"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_Post_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + string? documentSchemaRefId = null; + + document.Should().ContainPath("paths./supermarkets.post").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("postSupermarket"); + }); + + documentSchemaRefId = getElement.Should().ContainPath($"requestBody.content{EscapedJsonApiMediaType}.schema.allOf[0].$ref") + .ShouldBeSchemaReferenceId("createSupermarketRequestDocument").SchemaReferenceId; + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + string? resourceDataSchemaRefId = null; + + schemasElement.Should().ContainPath($"{documentSchemaRefId}.properties").With(propertiesElement => + { + resourceDataSchemaRefId = propertiesElement.Should().ContainPath("data.allOf[0].$ref") + .ShouldBeSchemaReferenceId("dataInCreateSupermarketRequest").SchemaReferenceId; + }); + + string? resourceRelationshipInPostRequestSchemaRefId = null; + + schemasElement.Should().ContainPath($"{resourceDataSchemaRefId}.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("attributes.allOf[0].$ref").ShouldBeSchemaReferenceId("attributesInCreateSupermarketRequest"); + + resourceRelationshipInPostRequestSchemaRefId = propertiesElement.Should().ContainPath("relationships.allOf[0].$ref") + .ShouldBeSchemaReferenceId("relationshipsInCreateSupermarketRequest").SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{resourceRelationshipInPostRequestSchemaRefId}.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("storeManager"); + propertiesElement.Should().ContainPath("storeManager.allOf[0].$ref").ShouldBeSchemaReferenceId("toOneStaffMemberInRequest"); + + propertiesElement.Should().ContainProperty("backupStoreManager"); + propertiesElement.Should().ContainPath("backupStoreManager.allOf[0].$ref").ShouldBeSchemaReferenceId("nullableToOneStaffMemberInRequest"); + + propertiesElement.Should().ContainProperty("cashiers"); + propertiesElement.Should().ContainPath("cashiers.allOf[0].$ref").ShouldBeSchemaReferenceId("toManyStaffMemberInRequest"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_PostRelationship_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./supermarkets/{id}/relationships/cashiers.post").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("postSupermarketCashiersRelationship"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_Patch_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + string? documentSchemaRefId = null; + + document.Should().ContainPath("paths./supermarkets/{id}.patch").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("patchSupermarket"); + }); + + documentSchemaRefId = getElement.Should().ContainPath($"requestBody.content{EscapedJsonApiMediaType}.schema.allOf[0].$ref") + .ShouldBeSchemaReferenceId("updateSupermarketRequestDocument").SchemaReferenceId; + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + string? resourceDataSchemaRefId = null; + + schemasElement.Should().ContainPath($"{documentSchemaRefId}.properties").With(propertiesElement => + { + resourceDataSchemaRefId = propertiesElement.Should().ContainPath("data.allOf[0].$ref") + .ShouldBeSchemaReferenceId("dataInUpdateSupermarketRequest").SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{resourceDataSchemaRefId}.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("attributes.allOf[0].$ref").ShouldBeSchemaReferenceId("attributesInUpdateSupermarketRequest"); + propertiesElement.Should().ContainPath("relationships.allOf[0].$ref").ShouldBeSchemaReferenceId("relationshipsInUpdateSupermarketRequest"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_PatchRelationship_endpoint_with_ToOne_relationship() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./supermarkets/{id}/relationships/storeManager.patch").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("patchSupermarketStoreManagerRelationship"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_PatchRelationship_endpoint_with_nullable_ToOne_relationship() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./supermarkets/{id}/relationships/backupStoreManager.patch").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("patchSupermarketBackupStoreManagerRelationship"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_PatchRelationship_endpoint_with_ToMany_relationship() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./supermarkets/{id}/relationships/cashiers.patch").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("patchSupermarketCashiersRelationship"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_Delete_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./supermarkets/{id}.delete").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("deleteSupermarket"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_DeleteRelationship_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./supermarkets/{id}/relationships/cashiers.delete").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("deleteSupermarketCashiersRelationship"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_PostOperations_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./operations.post").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("postOperations"); + }); + + getElement.Should().ContainPath($"requestBody.content{EscapedOperationsMediaType}.schema.allOf[0].$ref") + .ShouldBeSchemaReferenceId("operationsRequestDocument"); + + getElement.Should().ContainPath($"responses.200.content{EscapedOperationsMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("operationsResponseDocument"); + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + schemasElement.Should().ContainPath("addOperationCode.enum").With(codeElement => codeElement.Should().ContainArrayElement("add")); + schemasElement.Should().ContainPath("updateOperationCode.enum").With(codeElement => codeElement.Should().ContainArrayElement("update")); + schemasElement.Should().ContainPath("removeOperationCode.enum").With(codeElement => codeElement.Should().ContainArrayElement("remove")); + + schemasElement.Should().ContainPath("atomicOperation.discriminator.mapping").With(mappingElement => + { + mappingElement.Should().ContainPath("addStaffMember").ShouldBeSchemaReferenceId("createStaffMemberOperation"); + mappingElement.Should().ContainPath("addSupermarket").ShouldBeSchemaReferenceId("createSupermarketOperation"); + mappingElement.Should().ContainPath("addToSupermarketCashiers").ShouldBeSchemaReferenceId("addToSupermarketCashiersRelationshipOperation"); + + mappingElement.Should().ContainPath("removeFromSupermarketCashiers") + .ShouldBeSchemaReferenceId("removeFromSupermarketCashiersRelationshipOperation"); + + mappingElement.Should().ContainPath("removeStaffMember").ShouldBeSchemaReferenceId("deleteStaffMemberOperation"); + mappingElement.Should().ContainPath("removeSupermarket").ShouldBeSchemaReferenceId("deleteSupermarketOperation"); + mappingElement.Should().ContainPath("updateStaffMember").ShouldBeSchemaReferenceId("updateStaffMemberOperation"); + mappingElement.Should().ContainPath("updateSupermarket").ShouldBeSchemaReferenceId("updateSupermarketOperation"); + + mappingElement.Should().ContainPath("updateSupermarketBackupStoreManager") + .ShouldBeSchemaReferenceId("updateSupermarketBackupStoreManagerRelationshipOperation"); + + mappingElement.Should().ContainPath("updateSupermarketCashiers").ShouldBeSchemaReferenceId("updateSupermarketCashiersRelationshipOperation"); + + mappingElement.Should().ContainPath("updateSupermarketStoreManager") + .ShouldBeSchemaReferenceId("updateSupermarketStoreManagerRelationshipOperation"); + }); + + schemasElement.Should().ContainPath("createSupermarketOperation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("data.allOf[0].$ref").ShouldBeSchemaReferenceId("dataInCreateSupermarketRequest"); + }); + + schemasElement.Should().ContainPath("updateSupermarketOperation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("supermarketIdentifierInRequest"); + propertiesElement.Should().ContainPath("data.allOf[0].$ref").ShouldBeSchemaReferenceId("dataInUpdateSupermarketRequest"); + }); + + schemasElement.Should().ContainPath("deleteSupermarketOperation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("supermarketIdentifierInRequest"); + }); + + schemasElement.Should().ContainPath("updateSupermarketStoreManagerRelationshipOperation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("supermarketStoreManagerRelationshipIdentifier"); + propertiesElement.Should().ContainPath("data.allOf[0].$ref").ShouldBeSchemaReferenceId("staffMemberIdentifierInRequest"); + }); + + schemasElement.Should().ContainPath("updateSupermarketBackupStoreManagerRelationshipOperation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("supermarketBackupStoreManagerRelationshipIdentifier"); + propertiesElement.Should().ContainPath("data.allOf[0].$ref").ShouldBeSchemaReferenceId("staffMemberIdentifierInRequest"); + }); + + schemasElement.Should().ContainPath("updateSupermarketCashiersRelationshipOperation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("supermarketCashiersRelationshipIdentifier"); + propertiesElement.Should().ContainPath("data.items.$ref").ShouldBeSchemaReferenceId("staffMemberIdentifierInRequest"); + }); + + schemasElement.Should().ContainPath("addToSupermarketCashiersRelationshipOperation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("supermarketCashiersRelationshipIdentifier"); + propertiesElement.Should().ContainPath("data.items.$ref").ShouldBeSchemaReferenceId("staffMemberIdentifierInRequest"); + }); + + schemasElement.Should().ContainPath("removeFromSupermarketCashiersRelationshipOperation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("supermarketCashiersRelationshipIdentifier"); + propertiesElement.Should().ContainPath("data.items.$ref").ShouldBeSchemaReferenceId("staffMemberIdentifierInRequest"); + }); + + schemasElement.Should().ContainPath("createStaffMemberOperation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("data.allOf[0].$ref").ShouldBeSchemaReferenceId("dataInCreateStaffMemberRequest"); + }); + + schemasElement.Should().ContainPath("updateStaffMemberOperation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("staffMemberIdentifierInRequest"); + propertiesElement.Should().ContainPath("data.allOf[0].$ref").ShouldBeSchemaReferenceId("dataInUpdateStaffMemberRequest"); + }); + + schemasElement.Should().ContainPath("deleteStaffMemberOperation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("staffMemberIdentifierInRequest"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_error_schema() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.errorResponseDocument"); + document.Should().ContainPath("components.schemas.errorTopLevelLinks"); + } +} diff --git a/test/OpenApiTests/NamingConventions/CamelCase/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/NamingConventions/CamelCase/GeneratedSwagger/swagger.g.json new file mode 100644 index 0000000000..7a22ed8d57 --- /dev/null +++ b/test/OpenApiTests/NamingConventions/CamelCase/GeneratedSwagger/swagger.g.json @@ -0,0 +1,5079 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "OpenApiTests", + "version": "1.0" + }, + "servers": [ + { + "url": "http://localhost" + } + ], + "paths": { + "/operations": { + "post": { + "tags": [ + "operations" + ], + "summary": "Performs multiple mutations in a linear and atomic manner.", + "operationId": "postOperations", + "requestBody": { + "description": "An array of mutation operations. For syntax, see the [Atomic Operations documentation](https://jsonapi.org/ext/atomic/).", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/operationsRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "All operations were successfully applied, which resulted in additional changes.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/operationsResponseDocument" + } + } + } + }, + "204": { + "description": "All operations were successfully applied, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "An operation is not accessible or a client-generated ID is used.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/staffMembers": { + "get": { + "tags": [ + "staffMembers" + ], + "summary": "Retrieves a collection of staffMembers.", + "operationId": "getStaffMemberCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found staffMembers, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/staffMemberCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "staffMembers" + ], + "summary": "Retrieves a collection of staffMembers without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headStaffMemberCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "staffMembers" + ], + "summary": "Creates a new staffMember.", + "operationId": "postStaffMember", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the staffMember to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createStaffMemberRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The staffMember was successfully created, which resulted in additional changes. The newly created staffMember is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created staffMember can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryStaffMemberResponseDocument" + } + } + } + }, + "204": { + "description": "The staffMember was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/staffMembers/{id}": { + "get": { + "tags": [ + "staffMembers" + ], + "summary": "Retrieves an individual staffMember by its identifier.", + "operationId": "getStaffMember", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the staffMember to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found staffMember.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryStaffMemberResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The staffMember does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "staffMembers" + ], + "summary": "Retrieves an individual staffMember by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headStaffMember", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the staffMember to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The staffMember does not exist." + } + } + }, + "patch": { + "tags": [ + "staffMembers" + ], + "summary": "Updates an existing staffMember.", + "operationId": "patchStaffMember", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the staffMember to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the staffMember to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateStaffMemberRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The staffMember was successfully updated, which resulted in additional changes. The updated staffMember is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryStaffMemberResponseDocument" + } + } + } + }, + "204": { + "description": "The staffMember was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The staffMember or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "staffMembers" + ], + "summary": "Deletes an existing staffMember by its identifier.", + "operationId": "deleteStaffMember", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the staffMember to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "responses": { + "204": { + "description": "The staffMember was successfully deleted." + }, + "404": { + "description": "The staffMember does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/supermarkets": { + "get": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves a collection of supermarkets.", + "operationId": "getSupermarketCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found supermarkets, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/supermarketCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves a collection of supermarkets without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headSupermarketCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "supermarkets" + ], + "summary": "Creates a new supermarket.", + "operationId": "postSupermarket", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the supermarket to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createSupermarketRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The supermarket was successfully created, which resulted in additional changes. The newly created supermarket is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created supermarket can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primarySupermarketResponseDocument" + } + } + } + }, + "204": { + "description": "The supermarket was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/supermarkets/{id}": { + "get": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves an individual supermarket by its identifier.", + "operationId": "getSupermarket", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found supermarket.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primarySupermarketResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves an individual supermarket by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headSupermarket", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The supermarket does not exist." + } + } + }, + "patch": { + "tags": [ + "supermarkets" + ], + "summary": "Updates an existing supermarket.", + "operationId": "patchSupermarket", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the supermarket to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateSupermarketRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The supermarket was successfully updated, which resulted in additional changes. The updated supermarket is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primarySupermarketResponseDocument" + } + } + } + }, + "204": { + "description": "The supermarket was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The supermarket or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "supermarkets" + ], + "summary": "Deletes an existing supermarket by its identifier.", + "operationId": "deleteSupermarket", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "responses": { + "204": { + "description": "The supermarket was successfully deleted." + }, + "404": { + "description": "The supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/supermarkets/{id}/backupStoreManager": { + "get": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staffMember of an individual supermarket's backupStoreManager relationship.", + "operationId": "getSupermarketBackupStoreManager", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staffMember to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found staffMember, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullableSecondaryStaffMemberResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staffMember of an individual supermarket's backupStoreManager relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headSupermarketBackupStoreManager", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staffMember to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The supermarket does not exist." + } + } + } + }, + "/supermarkets/{id}/relationships/backupStoreManager": { + "get": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staffMember identity of an individual supermarket's backupStoreManager relationship.", + "operationId": "getSupermarketBackupStoreManagerRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staffMember identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found staffMember identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullableStaffMemberIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staffMember identity of an individual supermarket's backupStoreManager relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headSupermarketBackupStoreManagerRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staffMember identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The supermarket does not exist." + } + } + }, + "patch": { + "tags": [ + "supermarkets" + ], + "summary": "Clears or assigns an existing staffMember to the backupStoreManager relationship of an individual supermarket.", + "operationId": "patchSupermarketBackupStoreManagerRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose backupStoreManager relationship to assign or clear.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identity of the staffMember to assign to the backupStoreManager relationship, or `null` to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneStaffMemberInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The backupStoreManager relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The supermarket or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/supermarkets/{id}/cashiers": { + "get": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staffMembers of an individual supermarket's cashiers relationship.", + "operationId": "getSupermarketCashiers", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staffMembers to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found staffMembers, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/staffMemberCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staffMembers of an individual supermarket's cashiers relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headSupermarketCashiers", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staffMembers to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The supermarket does not exist." + } + } + } + }, + "/supermarkets/{id}/relationships/cashiers": { + "get": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staffMember identities of an individual supermarket's cashiers relationship.", + "operationId": "getSupermarketCashiersRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staffMember identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found staffMember identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/staffMemberIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staffMember identities of an individual supermarket's cashiers relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headSupermarketCashiersRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staffMember identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The supermarket does not exist." + } + } + }, + "post": { + "tags": [ + "supermarkets" + ], + "summary": "Adds existing staffMembers to the cashiers relationship of an individual supermarket.", + "operationId": "postSupermarketCashiersRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket to add staffMembers to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the staffMembers to add to the cashiers relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStaffMemberInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The staffMembers were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The supermarket or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "supermarkets" + ], + "summary": "Assigns existing staffMembers to the cashiers relationship of an individual supermarket.", + "operationId": "patchSupermarketCashiersRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose cashiers relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the staffMembers to assign to the cashiers relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStaffMemberInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The cashiers relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The supermarket or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "supermarkets" + ], + "summary": "Removes existing staffMembers from the cashiers relationship of an individual supermarket.", + "operationId": "deleteSupermarketCashiersRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket to remove staffMembers from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the staffMembers to remove from the cashiers relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStaffMemberInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The staffMembers were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The supermarket or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/supermarkets/{id}/storeManager": { + "get": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staffMember of an individual supermarket's storeManager relationship.", + "operationId": "getSupermarketStoreManager", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staffMember to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found staffMember, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/secondaryStaffMemberResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staffMember of an individual supermarket's storeManager relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headSupermarketStoreManager", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staffMember to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The supermarket does not exist." + } + } + } + }, + "/supermarkets/{id}/relationships/storeManager": { + "get": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staffMember identity of an individual supermarket's storeManager relationship.", + "operationId": "getSupermarketStoreManagerRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staffMember identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found staffMember identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/staffMemberIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staffMember identity of an individual supermarket's storeManager relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headSupermarketStoreManagerRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staffMember identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The supermarket does not exist." + } + } + }, + "patch": { + "tags": [ + "supermarkets" + ], + "summary": "Assigns an existing staffMember to the storeManager relationship of an individual supermarket.", + "operationId": "patchSupermarketStoreManagerRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose storeManager relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identity of the staffMember to assign to the storeManager relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneStaffMemberInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The storeManager relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The supermarket or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "addOperationCode": { + "enum": [ + "add" + ], + "type": "string" + }, + "addToSupermarketCashiersRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarketCashiersRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staffMemberIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "atomicOperation": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "type": "string" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "addStaffMember": "#/components/schemas/createStaffMemberOperation", + "addSupermarket": "#/components/schemas/createSupermarketOperation", + "addToSupermarketCashiers": "#/components/schemas/addToSupermarketCashiersRelationshipOperation", + "removeFromSupermarketCashiers": "#/components/schemas/removeFromSupermarketCashiersRelationshipOperation", + "removeStaffMember": "#/components/schemas/deleteStaffMemberOperation", + "removeSupermarket": "#/components/schemas/deleteSupermarketOperation", + "updateStaffMember": "#/components/schemas/updateStaffMemberOperation", + "updateSupermarket": "#/components/schemas/updateSupermarketOperation", + "updateSupermarketBackupStoreManager": "#/components/schemas/updateSupermarketBackupStoreManagerRelationshipOperation", + "updateSupermarketCashiers": "#/components/schemas/updateSupermarketCashiersRelationshipOperation", + "updateSupermarketStoreManager": "#/components/schemas/updateSupermarketStoreManagerRelationshipOperation" + } + }, + "x-abstract": true + }, + "atomicResult": { + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "attributesInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "staffMembers": "#/components/schemas/attributesInCreateStaffMemberRequest", + "supermarkets": "#/components/schemas/attributesInCreateSupermarketRequest" + } + }, + "x-abstract": true + }, + "attributesInCreateStaffMemberRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "age": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateSupermarketRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "nameOfCity" + ], + "type": "object", + "properties": { + "nameOfCity": { + "type": "string" + }, + "kind": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarketType" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "staffMembers": "#/components/schemas/attributesInStaffMemberResponse", + "supermarkets": "#/components/schemas/attributesInSupermarketResponse" + } + }, + "x-abstract": true + }, + "attributesInStaffMemberResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "age": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInSupermarketResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "nameOfCity": { + "type": "string" + }, + "kind": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarketType" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "staffMembers": "#/components/schemas/attributesInUpdateStaffMemberRequest", + "supermarkets": "#/components/schemas/attributesInUpdateSupermarketRequest" + } + }, + "x-abstract": true + }, + "attributesInUpdateStaffMemberRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "age": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateSupermarketRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "nameOfCity": { + "type": "string" + }, + "kind": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarketType" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createStaffMemberOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateStaffMemberRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createStaffMemberRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateStaffMemberRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "createSupermarketOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateSupermarketRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createSupermarketRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateSupermarketRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "dataInCreateStaffMemberRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateStaffMemberRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateSupermarketRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateSupermarketRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateSupermarketRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInStaffMemberResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInStaffMemberResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInSupermarketResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInSupermarketResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInSupermarketResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateStaffMemberRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateStaffMemberRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateSupermarketRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateSupermarketRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateSupermarketRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "deleteStaffMemberOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/staffMemberIdentifierInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "deleteSupermarketOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarketIdentifierInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "errorLinks": { + "type": "object", + "properties": { + "about": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorObject": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorLinks" + } + ], + "nullable": true + }, + "status": { + "type": "string" + }, + "code": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/errorSource" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorResponseDocument": { + "required": [ + "errors", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorTopLevelLinks" + } + ] + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/errorObject" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorSource": { + "type": "object", + "properties": { + "pointer": { + "type": "string", + "nullable": true + }, + "parameter": { + "type": "string", + "nullable": true + }, + "header": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "identifierInRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "staffMembers": "#/components/schemas/staffMemberIdentifierInRequest", + "supermarkets": "#/components/schemas/supermarketIdentifierInRequest" + } + }, + "x-abstract": true + }, + "jsonapi": { + "type": "object", + "properties": { + "version": { + "type": "string" + }, + "ext": { + "type": "array", + "items": { + "type": "string" + } + }, + "profile": { + "type": "array", + "items": { + "type": "string" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "meta": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "nullableSecondaryStaffMemberResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInStaffMemberResponse" + } + ], + "nullable": true + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableStaffMemberIdentifierResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/staffMemberIdentifierInResponse" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableToOneStaffMemberInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/staffMemberIdentifierInRequest" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableToOneStaffMemberInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/staffMemberIdentifierInResponse" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "operationsRequestDocument": { + "required": [ + "atomic:operations" + ], + "type": "object", + "properties": { + "atomic:operations": { + "minItems": 1, + "type": "array", + "items": { + "$ref": "#/components/schemas/atomicOperation" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "operationsResponseDocument": { + "required": [ + "atomic:results", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "atomic:results": { + "minItems": 1, + "type": "array", + "items": { + "$ref": "#/components/schemas/atomicResult" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryStaffMemberResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInStaffMemberResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primarySupermarketResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInSupermarketResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "relationshipLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + } + }, + "additionalProperties": false + }, + "relationshipsInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "supermarkets": "#/components/schemas/relationshipsInCreateSupermarketRequest" + } + }, + "x-abstract": true + }, + "relationshipsInCreateSupermarketRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "required": [ + "storeManager" + ], + "type": "object", + "properties": { + "storeManager": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneStaffMemberInRequest" + } + ] + }, + "backupStoreManager": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneStaffMemberInRequest" + } + ] + }, + "cashiers": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStaffMemberInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "supermarkets": "#/components/schemas/relationshipsInSupermarketResponse" + } + }, + "x-abstract": true + }, + "relationshipsInSupermarketResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "type": "object", + "properties": { + "storeManager": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneStaffMemberInResponse" + } + ] + }, + "backupStoreManager": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneStaffMemberInResponse" + } + ] + }, + "cashiers": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStaffMemberInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "supermarkets": "#/components/schemas/relationshipsInUpdateSupermarketRequest" + } + }, + "x-abstract": true + }, + "relationshipsInUpdateSupermarketRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "storeManager": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneStaffMemberInRequest" + } + ] + }, + "backupStoreManager": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneStaffMemberInRequest" + } + ] + }, + "cashiers": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStaffMemberInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "removeFromSupermarketCashiersRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarketCashiersRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staffMemberIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "removeOperationCode": { + "enum": [ + "remove" + ], + "type": "string" + }, + "resourceCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceIdentifierCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceIdentifierTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceInCreateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "staffMembers": "#/components/schemas/dataInCreateStaffMemberRequest", + "supermarkets": "#/components/schemas/dataInCreateSupermarketRequest" + } + }, + "x-abstract": true + }, + "resourceInResponse": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "staffMembers": "#/components/schemas/dataInStaffMemberResponse", + "supermarkets": "#/components/schemas/dataInSupermarketResponse" + } + }, + "x-abstract": true + }, + "resourceInUpdateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "staffMembers": "#/components/schemas/dataInUpdateStaffMemberRequest", + "supermarkets": "#/components/schemas/dataInUpdateSupermarketRequest" + } + }, + "x-abstract": true + }, + "resourceLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceType": { + "enum": [ + "staffMembers", + "supermarkets" + ], + "type": "string" + }, + "secondaryStaffMemberResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInStaffMemberResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "staffMemberCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInStaffMemberResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "staffMemberIdentifierCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staffMemberIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "staffMemberIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "staffMemberIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/staffMemberResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "staffMemberIdentifierResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/staffMemberIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "staffMemberResourceType": { + "enum": [ + "staffMembers" + ], + "type": "string" + }, + "supermarketBackupStoreManagerRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarketResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarketBackupStoreManagerRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "supermarketBackupStoreManagerRelationshipName": { + "enum": [ + "backupStoreManager" + ], + "type": "string" + }, + "supermarketCashiersRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarketResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarketCashiersRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "supermarketCashiersRelationshipName": { + "enum": [ + "cashiers" + ], + "type": "string" + }, + "supermarketCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInSupermarketResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "supermarketIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "supermarketResourceType": { + "enum": [ + "supermarkets" + ], + "type": "string" + }, + "supermarketStoreManagerRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarketResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarketStoreManagerRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "supermarketStoreManagerRelationshipName": { + "enum": [ + "storeManager" + ], + "type": "string" + }, + "supermarketType": { + "enum": [ + "Traditional", + "Budget", + "Warehouse" + ], + "type": "string" + }, + "toManyStaffMemberInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staffMemberIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyStaffMemberInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staffMemberIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneStaffMemberInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/staffMemberIdentifierInRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneStaffMemberInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/staffMemberIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateOperationCode": { + "enum": [ + "update" + ], + "type": "string" + }, + "updateStaffMemberOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/staffMemberIdentifierInRequest" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateStaffMemberRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateStaffMemberRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateStaffMemberRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateSupermarketBackupStoreManagerRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarketBackupStoreManagerRelationshipIdentifier" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/staffMemberIdentifierInRequest" + } + ], + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateSupermarketCashiersRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarketCashiersRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staffMemberIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateSupermarketOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarketIdentifierInRequest" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateSupermarketRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateSupermarketRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateSupermarketRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateSupermarketStoreManagerRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarketStoreManagerRelationshipIdentifier" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/staffMemberIdentifierInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/test/OpenApiTests/NamingConventions/KebabCase/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/NamingConventions/KebabCase/GeneratedSwagger/swagger.g.json new file mode 100644 index 0000000000..1955060d71 --- /dev/null +++ b/test/OpenApiTests/NamingConventions/KebabCase/GeneratedSwagger/swagger.g.json @@ -0,0 +1,5079 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "OpenApiTests", + "version": "1.0" + }, + "servers": [ + { + "url": "http://localhost" + } + ], + "paths": { + "/operations": { + "post": { + "tags": [ + "operations" + ], + "summary": "Performs multiple mutations in a linear and atomic manner.", + "operationId": "post-operations", + "requestBody": { + "description": "An array of mutation operations. For syntax, see the [Atomic Operations documentation](https://jsonapi.org/ext/atomic/).", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/operations-request-document" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "All operations were successfully applied, which resulted in additional changes.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/operations-response-document" + } + } + } + }, + "204": { + "description": "All operations were successfully applied, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "403": { + "description": "An operation is not accessible or a client-generated ID is used.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "A resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/staff-members": { + "get": { + "tags": [ + "staff-members" + ], + "summary": "Retrieves a collection of staff-members.", + "operationId": "get-staff-member-collection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found staff-members, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/staff-member-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "staff-members" + ], + "summary": "Retrieves a collection of staff-members without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-staff-member-collection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "staff-members" + ], + "summary": "Creates a new staff-member.", + "operationId": "post-staff-member", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the staff-member to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/create-staff-member-request-document" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The staff-member was successfully created, which resulted in additional changes. The newly created staff-member is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created staff-member can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-staff-member-response-document" + } + } + } + }, + "204": { + "description": "The staff-member was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/staff-members/{id}": { + "get": { + "tags": [ + "staff-members" + ], + "summary": "Retrieves an individual staff-member by its identifier.", + "operationId": "get-staff-member", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the staff-member to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found staff-member.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-staff-member-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The staff-member does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "staff-members" + ], + "summary": "Retrieves an individual staff-member by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-staff-member", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the staff-member to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The staff-member does not exist." + } + } + }, + "patch": { + "tags": [ + "staff-members" + ], + "summary": "Updates an existing staff-member.", + "operationId": "patch-staff-member", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the staff-member to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the staff-member to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/update-staff-member-request-document" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The staff-member was successfully updated, which resulted in additional changes. The updated staff-member is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-staff-member-response-document" + } + } + } + }, + "204": { + "description": "The staff-member was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The staff-member or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "delete": { + "tags": [ + "staff-members" + ], + "summary": "Deletes an existing staff-member by its identifier.", + "operationId": "delete-staff-member", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the staff-member to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "responses": { + "204": { + "description": "The staff-member was successfully deleted." + }, + "404": { + "description": "The staff-member does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/supermarkets": { + "get": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves a collection of supermarkets.", + "operationId": "get-supermarket-collection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found supermarkets, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/supermarket-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves a collection of supermarkets without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-supermarket-collection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "supermarkets" + ], + "summary": "Creates a new supermarket.", + "operationId": "post-supermarket", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the supermarket to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/create-supermarket-request-document" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The supermarket was successfully created, which resulted in additional changes. The newly created supermarket is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created supermarket can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-supermarket-response-document" + } + } + } + }, + "204": { + "description": "The supermarket was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/supermarkets/{id}": { + "get": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves an individual supermarket by its identifier.", + "operationId": "get-supermarket", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found supermarket.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-supermarket-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves an individual supermarket by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-supermarket", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The supermarket does not exist." + } + } + }, + "patch": { + "tags": [ + "supermarkets" + ], + "summary": "Updates an existing supermarket.", + "operationId": "patch-supermarket", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the supermarket to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/update-supermarket-request-document" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The supermarket was successfully updated, which resulted in additional changes. The updated supermarket is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primary-supermarket-response-document" + } + } + } + }, + "204": { + "description": "The supermarket was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The supermarket or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "delete": { + "tags": [ + "supermarkets" + ], + "summary": "Deletes an existing supermarket by its identifier.", + "operationId": "delete-supermarket", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "responses": { + "204": { + "description": "The supermarket was successfully deleted." + }, + "404": { + "description": "The supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/supermarkets/{id}/backup-store-manager": { + "get": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staff-member of an individual supermarket's backup-store-manager relationship.", + "operationId": "get-supermarket-backup-store-manager", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staff-member to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found staff-member, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullable-secondary-staff-member-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staff-member of an individual supermarket's backup-store-manager relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-supermarket-backup-store-manager", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staff-member to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The supermarket does not exist." + } + } + } + }, + "/supermarkets/{id}/relationships/backup-store-manager": { + "get": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staff-member identity of an individual supermarket's backup-store-manager relationship.", + "operationId": "get-supermarket-backup-store-manager-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staff-member identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found staff-member identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullable-staff-member-identifier-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staff-member identity of an individual supermarket's backup-store-manager relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-supermarket-backup-store-manager-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staff-member identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The supermarket does not exist." + } + } + }, + "patch": { + "tags": [ + "supermarkets" + ], + "summary": "Clears or assigns an existing staff-member to the backup-store-manager relationship of an individual supermarket.", + "operationId": "patch-supermarket-backup-store-manager-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose backup-store-manager relationship to assign or clear.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identity of the staff-member to assign to the backup-store-manager relationship, or `null` to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/nullable-to-one-staff-member-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The backup-store-manager relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The supermarket or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/supermarkets/{id}/cashiers": { + "get": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staff-members of an individual supermarket's cashiers relationship.", + "operationId": "get-supermarket-cashiers", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staff-members to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found staff-members, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/staff-member-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staff-members of an individual supermarket's cashiers relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-supermarket-cashiers", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staff-members to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The supermarket does not exist." + } + } + } + }, + "/supermarkets/{id}/relationships/cashiers": { + "get": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staff-member identities of an individual supermarket's cashiers relationship.", + "operationId": "get-supermarket-cashiers-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staff-member identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found staff-member identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/staff-member-identifier-collection-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staff-member identities of an individual supermarket's cashiers relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-supermarket-cashiers-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staff-member identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The supermarket does not exist." + } + } + }, + "post": { + "tags": [ + "supermarkets" + ], + "summary": "Adds existing staff-members to the cashiers relationship of an individual supermarket.", + "operationId": "post-supermarket-cashiers-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket to add staff-members to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the staff-members to add to the cashiers relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-staff-member-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The staff-members were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The supermarket or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "patch": { + "tags": [ + "supermarkets" + ], + "summary": "Assigns existing staff-members to the cashiers relationship of an individual supermarket.", + "operationId": "patch-supermarket-cashiers-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose cashiers relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the staff-members to assign to the cashiers relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-staff-member-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The cashiers relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The supermarket or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "delete": { + "tags": [ + "supermarkets" + ], + "summary": "Removes existing staff-members from the cashiers relationship of an individual supermarket.", + "operationId": "delete-supermarket-cashiers-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket to remove staff-members from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the staff-members to remove from the cashiers relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-staff-member-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The staff-members were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The supermarket or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + }, + "/supermarkets/{id}/store-manager": { + "get": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staff-member of an individual supermarket's store-manager relationship.", + "operationId": "get-supermarket-store-manager", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staff-member to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found staff-member, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/secondary-staff-member-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staff-member of an individual supermarket's store-manager relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-supermarket-store-manager", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staff-member to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The supermarket does not exist." + } + } + } + }, + "/supermarkets/{id}/relationships/store-manager": { + "get": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staff-member identity of an individual supermarket's store-manager relationship.", + "operationId": "get-supermarket-store-manager-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staff-member identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found staff-member identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/staff-member-identifier-response-document" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + }, + "head": { + "tags": [ + "supermarkets" + ], + "summary": "Retrieves the related staff-member identity of an individual supermarket's store-manager relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "head-supermarket-store-manager-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose related staff-member identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The supermarket does not exist." + } + } + }, + "patch": { + "tags": [ + "supermarkets" + ], + "summary": "Assigns an existing staff-member to the store-manager relationship of an individual supermarket.", + "operationId": "patch-supermarket-store-manager-relationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the supermarket whose store-manager relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identity of the staff-member to assign to the store-manager relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/to-one-staff-member-in-request" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The store-manager relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "404": { + "description": "The supermarket or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/error-response-document" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "add-operation-code": { + "enum": [ + "add" + ], + "type": "string" + }, + "add-to-supermarket-cashiers-relationship-operation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomic-operation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/add-operation-code" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarket-cashiers-relationship-identifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staff-member-identifier-in-request" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "atomic-operation": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "type": "string" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "add-staff-member": "#/components/schemas/create-staff-member-operation", + "add-supermarket": "#/components/schemas/create-supermarket-operation", + "add-to-supermarket-cashiers": "#/components/schemas/add-to-supermarket-cashiers-relationship-operation", + "remove-from-supermarket-cashiers": "#/components/schemas/remove-from-supermarket-cashiers-relationship-operation", + "remove-staff-member": "#/components/schemas/delete-staff-member-operation", + "remove-supermarket": "#/components/schemas/delete-supermarket-operation", + "update-staff-member": "#/components/schemas/update-staff-member-operation", + "update-supermarket": "#/components/schemas/update-supermarket-operation", + "update-supermarket-backup-store-manager": "#/components/schemas/update-supermarket-backup-store-manager-relationship-operation", + "update-supermarket-cashiers": "#/components/schemas/update-supermarket-cashiers-relationship-operation", + "update-supermarket-store-manager": "#/components/schemas/update-supermarket-store-manager-relationship-operation" + } + }, + "x-abstract": true + }, + "atomic-result": { + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-response" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "attributes-in-create-request": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "staff-members": "#/components/schemas/attributes-in-create-staff-member-request", + "supermarkets": "#/components/schemas/attributes-in-create-supermarket-request" + } + }, + "x-abstract": true + }, + "attributes-in-create-staff-member-request": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-create-request" + }, + { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "age": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-create-supermarket-request": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-create-request" + }, + { + "required": [ + "name-of-city" + ], + "type": "object", + "properties": { + "name-of-city": { + "type": "string" + }, + "kind": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarket-type" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-response": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "staff-members": "#/components/schemas/attributes-in-staff-member-response", + "supermarkets": "#/components/schemas/attributes-in-supermarket-response" + } + }, + "x-abstract": true + }, + "attributes-in-staff-member-response": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-response" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "age": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-supermarket-response": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-response" + }, + { + "type": "object", + "properties": { + "name-of-city": { + "type": "string" + }, + "kind": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarket-type" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-update-request": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "staff-members": "#/components/schemas/attributes-in-update-staff-member-request", + "supermarkets": "#/components/schemas/attributes-in-update-supermarket-request" + } + }, + "x-abstract": true + }, + "attributes-in-update-staff-member-request": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-update-request" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "age": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributes-in-update-supermarket-request": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-update-request" + }, + { + "type": "object", + "properties": { + "name-of-city": { + "type": "string" + }, + "kind": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarket-type" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "create-staff-member-operation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomic-operation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/add-operation-code" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-create-staff-member-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "create-staff-member-request-document": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-create-staff-member-request" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "create-supermarket-operation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomic-operation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/add-operation-code" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-create-supermarket-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "create-supermarket-request-document": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-create-supermarket-request" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "data-in-create-staff-member-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-create-request" + }, + { + "type": "object", + "properties": { + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-create-staff-member-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-create-supermarket-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-create-request" + }, + { + "type": "object", + "properties": { + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-create-supermarket-request" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-create-supermarket-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-staff-member-response": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-response" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-staff-member-response" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-links" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-supermarket-response": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-response" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-supermarket-response" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-supermarket-response" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-links" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-update-staff-member-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-update-request" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-update-staff-member-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "data-in-update-supermarket-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resource-in-update-request" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributes-in-update-supermarket-request" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-update-supermarket-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "delete-staff-member-operation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomic-operation" + }, + { + "required": [ + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/remove-operation-code" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/staff-member-identifier-in-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "delete-supermarket-operation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomic-operation" + }, + { + "required": [ + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/remove-operation-code" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarket-identifier-in-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "error-links": { + "type": "object", + "properties": { + "about": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "error-object": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/error-links" + } + ], + "nullable": true + }, + "status": { + "type": "string" + }, + "code": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/error-source" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "error-response-document": { + "required": [ + "errors", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/error-top-level-links" + } + ] + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/error-object" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "error-source": { + "type": "object", + "properties": { + "pointer": { + "type": "string", + "nullable": true + }, + "parameter": { + "type": "string", + "nullable": true + }, + "header": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "error-top-level-links": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "identifier-in-request": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "staff-members": "#/components/schemas/staff-member-identifier-in-request", + "supermarkets": "#/components/schemas/supermarket-identifier-in-request" + } + }, + "x-abstract": true + }, + "jsonapi": { + "type": "object", + "properties": { + "version": { + "type": "string" + }, + "ext": { + "type": "array", + "items": { + "type": "string" + } + }, + "profile": { + "type": "array", + "items": { + "type": "string" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "meta": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "nullable-secondary-staff-member-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-top-level-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-staff-member-response" + } + ], + "nullable": true + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullable-staff-member-identifier-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-identifier-top-level-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/staff-member-identifier-in-response" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullable-to-one-staff-member-in-request": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/staff-member-identifier-in-request" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullable-to-one-staff-member-in-response": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationship-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/staff-member-identifier-in-response" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "operations-request-document": { + "required": [ + "atomic:operations" + ], + "type": "object", + "properties": { + "atomic:operations": { + "minItems": 1, + "type": "array", + "items": { + "$ref": "#/components/schemas/atomic-operation" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "operations-response-document": { + "required": [ + "atomic:results", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-top-level-links" + } + ] + }, + "atomic:results": { + "minItems": 1, + "type": "array", + "items": { + "$ref": "#/components/schemas/atomic-result" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primary-staff-member-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-top-level-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-staff-member-response" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primary-supermarket-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-top-level-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-supermarket-response" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "relationship-links": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + } + }, + "additionalProperties": false + }, + "relationships-in-create-request": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "supermarkets": "#/components/schemas/relationships-in-create-supermarket-request" + } + }, + "x-abstract": true + }, + "relationships-in-create-supermarket-request": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-create-request" + }, + { + "required": [ + "store-manager" + ], + "type": "object", + "properties": { + "store-manager": { + "allOf": [ + { + "$ref": "#/components/schemas/to-one-staff-member-in-request" + } + ] + }, + "backup-store-manager": { + "allOf": [ + { + "$ref": "#/components/schemas/nullable-to-one-staff-member-in-request" + } + ] + }, + "cashiers": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-staff-member-in-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationships-in-response": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "supermarkets": "#/components/schemas/relationships-in-supermarket-response" + } + }, + "x-abstract": true + }, + "relationships-in-supermarket-response": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-response" + }, + { + "type": "object", + "properties": { + "store-manager": { + "allOf": [ + { + "$ref": "#/components/schemas/to-one-staff-member-in-response" + } + ] + }, + "backup-store-manager": { + "allOf": [ + { + "$ref": "#/components/schemas/nullable-to-one-staff-member-in-response" + } + ] + }, + "cashiers": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-staff-member-in-response" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationships-in-update-request": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "supermarkets": "#/components/schemas/relationships-in-update-supermarket-request" + } + }, + "x-abstract": true + }, + "relationships-in-update-supermarket-request": { + "allOf": [ + { + "$ref": "#/components/schemas/relationships-in-update-request" + }, + { + "type": "object", + "properties": { + "store-manager": { + "allOf": [ + { + "$ref": "#/components/schemas/to-one-staff-member-in-request" + } + ] + }, + "backup-store-manager": { + "allOf": [ + { + "$ref": "#/components/schemas/nullable-to-one-staff-member-in-request" + } + ] + }, + "cashiers": { + "allOf": [ + { + "$ref": "#/components/schemas/to-many-staff-member-in-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "remove-from-supermarket-cashiers-relationship-operation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomic-operation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/remove-operation-code" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarket-cashiers-relationship-identifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staff-member-identifier-in-request" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "remove-operation-code": { + "enum": [ + "remove" + ], + "type": "string" + }, + "resource-collection-top-level-links": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resource-identifier-collection-top-level-links": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resource-identifier-top-level-links": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resource-in-create-request": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "staff-members": "#/components/schemas/data-in-create-staff-member-request", + "supermarkets": "#/components/schemas/data-in-create-supermarket-request" + } + }, + "x-abstract": true + }, + "resource-in-response": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "staff-members": "#/components/schemas/data-in-staff-member-response", + "supermarkets": "#/components/schemas/data-in-supermarket-response" + } + }, + "x-abstract": true + }, + "resource-in-update-request": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-type" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "staff-members": "#/components/schemas/data-in-update-staff-member-request", + "supermarkets": "#/components/schemas/data-in-update-supermarket-request" + } + }, + "x-abstract": true + }, + "resource-links": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resource-top-level-links": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resource-type": { + "enum": [ + "staff-members", + "supermarkets" + ], + "type": "string" + }, + "secondary-staff-member-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-top-level-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-staff-member-response" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "staff-member-collection-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-collection-top-level-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/data-in-staff-member-response" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "staff-member-identifier-collection-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-identifier-collection-top-level-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staff-member-identifier-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "staff-member-identifier-in-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifier-in-request" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "staff-member-identifier-in-response": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/staff-member-resource-type" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "staff-member-identifier-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-identifier-top-level-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/staff-member-identifier-in-response" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "staff-member-resource-type": { + "enum": [ + "staff-members" + ], + "type": "string" + }, + "supermarket-backup-store-manager-relationship-identifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarket-resource-type" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarket-backup-store-manager-relationship-name" + } + ] + } + }, + "additionalProperties": false + }, + "supermarket-backup-store-manager-relationship-name": { + "enum": [ + "backup-store-manager" + ], + "type": "string" + }, + "supermarket-cashiers-relationship-identifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarket-resource-type" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarket-cashiers-relationship-name" + } + ] + } + }, + "additionalProperties": false + }, + "supermarket-cashiers-relationship-name": { + "enum": [ + "cashiers" + ], + "type": "string" + }, + "supermarket-collection-response-document": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resource-collection-top-level-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/data-in-supermarket-response" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resource-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "supermarket-identifier-in-request": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifier-in-request" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "supermarket-resource-type": { + "enum": [ + "supermarkets" + ], + "type": "string" + }, + "supermarket-store-manager-relationship-identifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarket-resource-type" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarket-store-manager-relationship-name" + } + ] + } + }, + "additionalProperties": false + }, + "supermarket-store-manager-relationship-name": { + "enum": [ + "store-manager" + ], + "type": "string" + }, + "supermarket-type": { + "enum": [ + "Traditional", + "Budget", + "Warehouse" + ], + "type": "string" + }, + "to-many-staff-member-in-request": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staff-member-identifier-in-request" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "to-many-staff-member-in-response": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationship-links" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staff-member-identifier-in-response" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "to-one-staff-member-in-request": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/staff-member-identifier-in-request" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "to-one-staff-member-in-response": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationship-links" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/staff-member-identifier-in-response" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "update-operation-code": { + "enum": [ + "update" + ], + "type": "string" + }, + "update-staff-member-operation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomic-operation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/update-operation-code" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/staff-member-identifier-in-request" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-update-staff-member-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "update-staff-member-request-document": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-update-staff-member-request" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "update-supermarket-backup-store-manager-relationship-operation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomic-operation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/update-operation-code" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarket-backup-store-manager-relationship-identifier" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/staff-member-identifier-in-request" + } + ], + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "update-supermarket-cashiers-relationship-operation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomic-operation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/update-operation-code" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarket-cashiers-relationship-identifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staff-member-identifier-in-request" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "update-supermarket-operation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomic-operation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/update-operation-code" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarket-identifier-in-request" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-update-supermarket-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "update-supermarket-request-document": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/data-in-update-supermarket-request" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "update-supermarket-store-manager-relationship-operation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomic-operation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/update-operation-code" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/supermarket-store-manager-relationship-identifier" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/staff-member-identifier-in-request" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/JsonKebabCaseNamingPolicy.cs b/test/OpenApiTests/NamingConventions/KebabCase/JsonKebabCaseNamingPolicy.cs similarity index 80% rename from test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/JsonKebabCaseNamingPolicy.cs rename to test/OpenApiTests/NamingConventions/KebabCase/JsonKebabCaseNamingPolicy.cs index d47de4cf66..aff836a470 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/JsonKebabCaseNamingPolicy.cs +++ b/test/OpenApiTests/NamingConventions/KebabCase/JsonKebabCaseNamingPolicy.cs @@ -1,7 +1,7 @@ using System.Text; using System.Text.Json; -namespace JsonApiDotNetCoreTests.IntegrationTests.NamingConventions; +namespace OpenApiTests.NamingConventions.KebabCase; // Based on https://github.com/J0rgeSerran0/JsonNamingPolicy internal sealed class JsonKebabCaseNamingPolicy : JsonNamingPolicy @@ -36,9 +36,9 @@ public override string ConvertName(string name) if (position + 1 != spanName.Length) { - isNextLower = spanName[position + 1] > 96 && spanName[position + 1] < 123; - isNextUpper = spanName[position + 1] > 64 && spanName[position + 1] < 91; - isNextSpace = spanName[position + 1] == 32; + isNextLower = spanName[position + 1] is >= 'a' and <= 'z'; + isNextUpper = spanName[position + 1] is >= 'A' and <= 'Z'; + isNextSpace = spanName[position + 1] == ' '; } if (isCurrentSpace && (isPreviousSpace || isPreviousSeparator || isNextUpper || isNextSpace)) @@ -47,9 +47,9 @@ public override string ConvertName(string name) } else { - bool isCurrentUpper = spanName[position] > 64 && spanName[position] < 91; - bool isPreviousLower = spanName[position - 1] > 96 && spanName[position - 1] < 123; - bool isPreviousNumber = spanName[position - 1] > 47 && spanName[position - 1] < 58; + bool isCurrentUpper = spanName[position] is >= 'A' and <= 'Z'; + bool isPreviousLower = spanName[position - 1] is >= 'a' and <= 'z'; + bool isPreviousNumber = spanName[position - 1] is >= '0' and <= '9'; if (isCurrentUpper && (isPreviousLower || isPreviousNumber || isNextLower || isNextSpace)) { @@ -76,6 +76,6 @@ public override string ConvertName(string name) } } - return stringBuilder.ToString().ToLower(); + return stringBuilder.ToString().ToLowerInvariant(); } } diff --git a/test/OpenApiTests/NamingConventions/KebabCase/KebabCaseNamingConventionStartup.cs b/test/OpenApiTests/NamingConventions/KebabCase/KebabCaseNamingConventionStartup.cs new file mode 100644 index 0000000000..cacd639813 --- /dev/null +++ b/test/OpenApiTests/NamingConventions/KebabCase/KebabCaseNamingConventionStartup.cs @@ -0,0 +1,21 @@ +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.Configuration; +using TestBuildingBlocks; + +namespace OpenApiTests.NamingConventions.KebabCase; + +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +public sealed class KebabCaseNamingConventionStartup : OpenApiStartup + where TDbContext : TestableDbContext +{ + protected override void SetJsonApiOptions(JsonApiOptions options) + { + base.SetJsonApiOptions(options); + + options.IncludeJsonApiVersion = true; + options.SerializerOptions.PropertyNamingPolicy = JsonKebabCaseNamingPolicy.Instance; + options.SerializerOptions.DictionaryKeyPolicy = JsonKebabCaseNamingPolicy.Instance; + options.SerializerOptions.Converters.Add(new JsonStringEnumConverter()); + } +} diff --git a/test/OpenApiTests/NamingConventions/KebabCase/KebabCaseTests.cs b/test/OpenApiTests/NamingConventions/KebabCase/KebabCaseTests.cs new file mode 100644 index 0000000000..077d7ec5ed --- /dev/null +++ b/test/OpenApiTests/NamingConventions/KebabCase/KebabCaseTests.cs @@ -0,0 +1,692 @@ +using System.Text.Json; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.NamingConventions.KebabCase; + +public sealed class KebabCaseTests : IClassFixture, NamingConventionDbContext>> +{ + private const string EscapedJsonApiMediaType = "['application/vnd.api+json; ext=openapi']"; + private const string EscapedOperationsMediaType = "['application/vnd.api+json; ext=atomic; ext=openapi']"; + + private readonly OpenApiTestContext, NamingConventionDbContext> _testContext; + + public KebabCaseTests(OpenApiTestContext, NamingConventionDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + + testContext.SetTestOutputHelper(testOutputHelper); + testContext.SwaggerDocumentOutputDirectory = $"{GetType().Namespace!.Replace('.', '/')}/GeneratedSwagger"; + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetCollection_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + string? documentSchemaRefId = null; + + document.Should().ContainPath("paths./supermarkets.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("get-supermarket-collection"); + }); + + documentSchemaRefId = getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("supermarket-collection-response-document").SchemaReferenceId; + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + string? topLevelLinksSchemaRefId = null; + string? resourceDataSchemaRefId = null; + + schemasElement.Should().ContainPath($"{documentSchemaRefId}.properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("jsonapi.allOf[0].$ref").ShouldBeSchemaReferenceId("jsonapi"); + + topLevelLinksSchemaRefId = propertiesElement.Should().ContainPath("links.allOf[0].$ref") + .ShouldBeSchemaReferenceId("resource-collection-top-level-links").SchemaReferenceId; + + resourceDataSchemaRefId = propertiesElement.Should().ContainPath("data.items.$ref").ShouldBeSchemaReferenceId("data-in-supermarket-response") + .SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{topLevelLinksSchemaRefId}.properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("self"); + propertiesElement.Should().ContainProperty("describedby"); + propertiesElement.Should().ContainProperty("first"); + propertiesElement.Should().ContainProperty("last"); + propertiesElement.Should().ContainProperty("prev"); + propertiesElement.Should().ContainProperty("next"); + }); + + string? resourceLinksSchemaRefId = null; + string? resourceAttributesInResponseSchemaRefId = null; + string? resourceRelationshipInResponseSchemaRefId = null; + + string abstractResourceDataSchemaRefId = schemasElement.Should().ContainPath($"{resourceDataSchemaRefId}.allOf[0].$ref") + .ShouldBeSchemaReferenceId("resource-in-response").SchemaReferenceId; + + schemasElement.Should().ContainPath($"{abstractResourceDataSchemaRefId}.discriminator.mapping").With(mappingElement => + { + mappingElement.Should().ContainPath("supermarkets").ShouldBeSchemaReferenceId("data-in-supermarket-response"); + mappingElement.Should().ContainPath("staff-members").ShouldBeSchemaReferenceId("data-in-staff-member-response"); + }); + + schemasElement.Should().ContainPath($"{resourceDataSchemaRefId}.allOf[1].properties").With(propertiesElement => + { + resourceLinksSchemaRefId = propertiesElement.Should().ContainPath("links.allOf[0].$ref").ShouldBeSchemaReferenceId("resource-links") + .SchemaReferenceId; + + resourceAttributesInResponseSchemaRefId = propertiesElement.Should().ContainPath("attributes.allOf[0].$ref") + .ShouldBeSchemaReferenceId("attributes-in-supermarket-response").SchemaReferenceId; + + resourceRelationshipInResponseSchemaRefId = propertiesElement.Should().ContainPath("relationships.allOf[0].$ref") + .ShouldBeSchemaReferenceId("relationships-in-supermarket-response").SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{resourceLinksSchemaRefId}.properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("self"); + }); + + schemasElement.Should().ContainPath($"{resourceAttributesInResponseSchemaRefId}.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("name-of-city"); + propertiesElement.Should().ContainProperty("kind"); + propertiesElement.Should().ContainPath("kind.allOf[0].$ref").ShouldBeSchemaReferenceId("supermarket-type"); + }); + + string? nullableToOneResourceResponseDataSchemaRefId = null; + + schemasElement.Should().ContainPath($"{resourceRelationshipInResponseSchemaRefId}.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("store-manager"); + + propertiesElement.Should().ContainPath("store-manager.allOf[0].$ref").ShouldBeSchemaReferenceId("to-one-staff-member-in-response"); + + nullableToOneResourceResponseDataSchemaRefId = propertiesElement.Should().ContainPath("backup-store-manager.allOf[0].$ref") + .ShouldBeSchemaReferenceId("nullable-to-one-staff-member-in-response").SchemaReferenceId; + + propertiesElement.Should().ContainProperty("cashiers"); + propertiesElement.Should().ContainPath("cashiers.allOf[0].$ref").ShouldBeSchemaReferenceId("to-many-staff-member-in-response"); + }); + + string? relationshipLinksSchemaRefId = null; + string? relatedResourceIdentifierSchemaRefId = null; + + schemasElement.Should().ContainPath($"{nullableToOneResourceResponseDataSchemaRefId}.properties").With(propertiesElement => + { + relationshipLinksSchemaRefId = propertiesElement.Should().ContainPath("links.allOf[0].$ref").ShouldBeSchemaReferenceId("relationship-links") + .SchemaReferenceId; + + relatedResourceIdentifierSchemaRefId = propertiesElement.Should().ContainPath("data.allOf[0].$ref") + .ShouldBeSchemaReferenceId("staff-member-identifier-in-response").SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{relationshipLinksSchemaRefId}.properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("self"); + propertiesElement.Should().ContainProperty("related"); + }); + + string? relatedResourceTypeSchemaRefId = null; + + schemasElement.Should().ContainPath($"{relatedResourceIdentifierSchemaRefId}.properties").With(propertiesElement => + { + relatedResourceTypeSchemaRefId = propertiesElement.Should().ContainPath("type.allOf[0].$ref") + .ShouldBeSchemaReferenceId("staff-member-resource-type").SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{relatedResourceTypeSchemaRefId}.enum").With(codeElement => + { + codeElement.Should().ContainArrayElement("staff-members"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetSingle_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + string? documentSchemaRefId = null; + + document.Should().ContainPath("paths./supermarkets/{id}.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("get-supermarket"); + }); + + documentSchemaRefId = getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("primary-supermarket-response-document").SchemaReferenceId; + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + string? topLevelLinksSchemaRefId = null; + + schemasElement.Should().ContainPath($"{documentSchemaRefId}.properties").With(propertiesElement => + { + topLevelLinksSchemaRefId = propertiesElement.Should().ContainPath("links.allOf[0].$ref").ShouldBeSchemaReferenceId("resource-top-level-links") + .SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{topLevelLinksSchemaRefId}.properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("self"); + propertiesElement.Should().ContainProperty("describedby"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetSecondary_endpoint_with_single_resource() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + string? documentSchemaRefId = null; + + document.Should().ContainPath("paths./supermarkets/{id}/store-manager.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("get-supermarket-store-manager"); + }); + + documentSchemaRefId = getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("secondary-staff-member-response-document").SchemaReferenceId; + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + string? resourceDataSchemaRefId = null; + + schemasElement.Should().ContainPath($"{documentSchemaRefId}.properties").With(propertiesElement => + { + resourceDataSchemaRefId = propertiesElement.Should().ContainPath("data.allOf[0].$ref") + .ShouldBeSchemaReferenceId("data-in-staff-member-response").SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{resourceDataSchemaRefId}.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("attributes.allOf[0].$ref").ShouldBeSchemaReferenceId("attributes-in-staff-member-response"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetSecondary_endpoint_with_nullable_resource() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./supermarkets/{id}/backup-store-manager.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("get-supermarket-backup-store-manager"); + }); + + getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("nullable-secondary-staff-member-response-document"); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetSecondary_endpoint_with_resources() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./supermarkets/{id}/cashiers.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("get-supermarket-cashiers"); + }); + + getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("staff-member-collection-response-document"); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetRelationship_endpoint_with_ToOne_relationship() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + string? documentSchemaRefId = null; + + document.Should().ContainPath("paths./supermarkets/{id}/relationships/store-manager.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("get-supermarket-store-manager-relationship"); + }); + + documentSchemaRefId = getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("staff-member-identifier-response-document").SchemaReferenceId; + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + string? topLevelLinksSchemaRefId = null; + + schemasElement.Should().ContainPath($"{documentSchemaRefId}.properties").With(propertiesElement => + { + topLevelLinksSchemaRefId = propertiesElement.Should().ContainPath("links.allOf[0].$ref") + .ShouldBeSchemaReferenceId("resource-identifier-top-level-links").SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{topLevelLinksSchemaRefId}.properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("self"); + propertiesElement.Should().ContainProperty("describedby"); + propertiesElement.Should().ContainProperty("related"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetRelationship_endpoint_with_nullable_ToOne_relationship() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./supermarkets/{id}/relationships/backup-store-manager.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("get-supermarket-backup-store-manager-relationship"); + }); + + getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("nullable-staff-member-identifier-response-document"); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetRelationship_endpoint_with_ToMany_relationship() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + string? documentSchemaRefId = null; + + document.Should().ContainPath("paths./supermarkets/{id}/relationships/cashiers.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("get-supermarket-cashiers-relationship"); + }); + + documentSchemaRefId = getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("staff-member-identifier-collection-response-document").SchemaReferenceId; + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + string? topLevelLinksSchemaRefId = null; + + schemasElement.Should().ContainPath($"{documentSchemaRefId}.properties").With(propertiesElement => + { + topLevelLinksSchemaRefId = propertiesElement.Should().ContainPath("links.allOf[0].$ref") + .ShouldBeSchemaReferenceId("resource-identifier-collection-top-level-links").SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{topLevelLinksSchemaRefId}.properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("self"); + propertiesElement.Should().ContainProperty("describedby"); + propertiesElement.Should().ContainProperty("related"); + propertiesElement.Should().ContainProperty("first"); + propertiesElement.Should().ContainProperty("last"); + propertiesElement.Should().ContainProperty("prev"); + propertiesElement.Should().ContainProperty("next"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_Post_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + string? documentSchemaRefId = null; + + document.Should().ContainPath("paths./supermarkets.post").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("post-supermarket"); + }); + + documentSchemaRefId = getElement.Should().ContainPath($"requestBody.content{EscapedJsonApiMediaType}.schema.allOf[0].$ref") + .ShouldBeSchemaReferenceId("create-supermarket-request-document").SchemaReferenceId; + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + string? resourceDataSchemaRefId = null; + + schemasElement.Should().ContainPath($"{documentSchemaRefId}.properties").With(propertiesElement => + { + resourceDataSchemaRefId = propertiesElement.Should().ContainPath("data.allOf[0].$ref") + .ShouldBeSchemaReferenceId("data-in-create-supermarket-request").SchemaReferenceId; + }); + + string? resourceRelationshipInPostRequestSchemaRefId = null; + + schemasElement.Should().ContainPath($"{resourceDataSchemaRefId}.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("attributes.allOf[0].$ref").ShouldBeSchemaReferenceId("attributes-in-create-supermarket-request"); + + resourceRelationshipInPostRequestSchemaRefId = propertiesElement.Should().ContainPath("relationships.allOf[0].$ref") + .ShouldBeSchemaReferenceId("relationships-in-create-supermarket-request").SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{resourceRelationshipInPostRequestSchemaRefId}.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("store-manager"); + propertiesElement.Should().ContainPath("store-manager.allOf[0].$ref").ShouldBeSchemaReferenceId("to-one-staff-member-in-request"); + + propertiesElement.Should().ContainProperty("backup-store-manager"); + + propertiesElement.Should().ContainPath("backup-store-manager.allOf[0].$ref") + .ShouldBeSchemaReferenceId("nullable-to-one-staff-member-in-request"); + + propertiesElement.Should().ContainProperty("cashiers"); + propertiesElement.Should().ContainPath("cashiers.allOf[0].$ref").ShouldBeSchemaReferenceId("to-many-staff-member-in-request"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_PostRelationship_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./supermarkets/{id}/relationships/cashiers.post").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("post-supermarket-cashiers-relationship"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_Patch_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + string? documentSchemaRefId = null; + + document.Should().ContainPath("paths./supermarkets/{id}.patch").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("patch-supermarket"); + }); + + documentSchemaRefId = getElement.Should().ContainPath($"requestBody.content{EscapedJsonApiMediaType}.schema.allOf[0].$ref") + .ShouldBeSchemaReferenceId("update-supermarket-request-document").SchemaReferenceId; + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + string? resourceDataSchemaRefId = null; + + schemasElement.Should().ContainPath($"{documentSchemaRefId}.properties").With(propertiesElement => + { + resourceDataSchemaRefId = propertiesElement.Should().ContainPath("data.allOf[0].$ref") + .ShouldBeSchemaReferenceId("data-in-update-supermarket-request").SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{resourceDataSchemaRefId}.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("attributes.allOf[0].$ref").ShouldBeSchemaReferenceId("attributes-in-update-supermarket-request"); + propertiesElement.Should().ContainPath("relationships.allOf[0].$ref").ShouldBeSchemaReferenceId("relationships-in-update-supermarket-request"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_PatchRelationship_endpoint_with_ToOne_relationship() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./supermarkets/{id}/relationships/store-manager.patch").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("patch-supermarket-store-manager-relationship"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_PatchRelationship_endpoint_with_nullable_ToOne_relationship() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./supermarkets/{id}/relationships/backup-store-manager.patch").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("patch-supermarket-backup-store-manager-relationship"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_PatchRelationship_endpoint_with_ToMany_relationship() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./supermarkets/{id}/relationships/cashiers.patch").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("patch-supermarket-cashiers-relationship"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_Delete_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./supermarkets/{id}.delete").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("delete-supermarket"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_DeleteRelationship_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./supermarkets/{id}/relationships/cashiers.delete").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("delete-supermarket-cashiers-relationship"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_PostOperations_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./operations.post").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("post-operations"); + }); + + getElement.Should().ContainPath($"requestBody.content{EscapedOperationsMediaType}.schema.allOf[0].$ref") + .ShouldBeSchemaReferenceId("operations-request-document"); + + getElement.Should().ContainPath($"responses.200.content{EscapedOperationsMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("operations-response-document"); + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + schemasElement.Should().ContainPath("add-operation-code.enum").With(codeElement => codeElement.Should().ContainArrayElement("add")); + schemasElement.Should().ContainPath("update-operation-code.enum").With(codeElement => codeElement.Should().ContainArrayElement("update")); + schemasElement.Should().ContainPath("remove-operation-code.enum").With(codeElement => codeElement.Should().ContainArrayElement("remove")); + + schemasElement.Should().ContainPath("atomic-operation.discriminator.mapping").With(mappingElement => + { + mappingElement.Should().ContainPath("add-staff-member").ShouldBeSchemaReferenceId("create-staff-member-operation"); + mappingElement.Should().ContainPath("add-supermarket").ShouldBeSchemaReferenceId("create-supermarket-operation"); + + mappingElement.Should().ContainPath("add-to-supermarket-cashiers") + .ShouldBeSchemaReferenceId("add-to-supermarket-cashiers-relationship-operation"); + + mappingElement.Should().ContainPath("remove-from-supermarket-cashiers") + .ShouldBeSchemaReferenceId("remove-from-supermarket-cashiers-relationship-operation"); + + mappingElement.Should().ContainPath("remove-staff-member").ShouldBeSchemaReferenceId("delete-staff-member-operation"); + mappingElement.Should().ContainPath("remove-supermarket").ShouldBeSchemaReferenceId("delete-supermarket-operation"); + mappingElement.Should().ContainPath("update-staff-member").ShouldBeSchemaReferenceId("update-staff-member-operation"); + mappingElement.Should().ContainPath("update-supermarket").ShouldBeSchemaReferenceId("update-supermarket-operation"); + + mappingElement.Should().ContainPath("update-supermarket-backup-store-manager") + .ShouldBeSchemaReferenceId("update-supermarket-backup-store-manager-relationship-operation"); + + mappingElement.Should().ContainPath("update-supermarket-cashiers") + .ShouldBeSchemaReferenceId("update-supermarket-cashiers-relationship-operation"); + + mappingElement.Should().ContainPath("update-supermarket-store-manager") + .ShouldBeSchemaReferenceId("update-supermarket-store-manager-relationship-operation"); + }); + + schemasElement.Should().ContainPath("create-supermarket-operation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("data.allOf[0].$ref").ShouldBeSchemaReferenceId("data-in-create-supermarket-request"); + }); + + schemasElement.Should().ContainPath("update-supermarket-operation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("supermarket-identifier-in-request"); + propertiesElement.Should().ContainPath("data.allOf[0].$ref").ShouldBeSchemaReferenceId("data-in-update-supermarket-request"); + }); + + schemasElement.Should().ContainPath("delete-supermarket-operation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("supermarket-identifier-in-request"); + }); + + schemasElement.Should().ContainPath("update-supermarket-store-manager-relationship-operation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("supermarket-store-manager-relationship-identifier"); + propertiesElement.Should().ContainPath("data.allOf[0].$ref").ShouldBeSchemaReferenceId("staff-member-identifier-in-request"); + }); + + schemasElement.Should().ContainPath("update-supermarket-backup-store-manager-relationship-operation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref") + .ShouldBeSchemaReferenceId("supermarket-backup-store-manager-relationship-identifier"); + + propertiesElement.Should().ContainPath("data.allOf[0].$ref").ShouldBeSchemaReferenceId("staff-member-identifier-in-request"); + }); + + schemasElement.Should().ContainPath("update-supermarket-cashiers-relationship-operation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("supermarket-cashiers-relationship-identifier"); + propertiesElement.Should().ContainPath("data.items.$ref").ShouldBeSchemaReferenceId("staff-member-identifier-in-request"); + }); + + schemasElement.Should().ContainPath("add-to-supermarket-cashiers-relationship-operation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("supermarket-cashiers-relationship-identifier"); + propertiesElement.Should().ContainPath("data.items.$ref").ShouldBeSchemaReferenceId("staff-member-identifier-in-request"); + }); + + schemasElement.Should().ContainPath("remove-from-supermarket-cashiers-relationship-operation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("supermarket-cashiers-relationship-identifier"); + propertiesElement.Should().ContainPath("data.items.$ref").ShouldBeSchemaReferenceId("staff-member-identifier-in-request"); + }); + + schemasElement.Should().ContainPath("create-staff-member-operation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("data.allOf[0].$ref").ShouldBeSchemaReferenceId("data-in-create-staff-member-request"); + }); + + schemasElement.Should().ContainPath("update-staff-member-operation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("staff-member-identifier-in-request"); + propertiesElement.Should().ContainPath("data.allOf[0].$ref").ShouldBeSchemaReferenceId("data-in-update-staff-member-request"); + }); + + schemasElement.Should().ContainPath("delete-staff-member-operation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("staff-member-identifier-in-request"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_error_schema() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.error-response-document"); + document.Should().ContainPath("components.schemas.error-top-level-links"); + } +} diff --git a/test/OpenApiTests/NamingConventions/NamingConventionDbContext.cs b/test/OpenApiTests/NamingConventions/NamingConventionDbContext.cs new file mode 100644 index 0000000000..8fa74a219b --- /dev/null +++ b/test/OpenApiTests/NamingConventions/NamingConventionDbContext.cs @@ -0,0 +1,12 @@ +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; +using TestBuildingBlocks; + +namespace OpenApiTests.NamingConventions; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public sealed class NamingConventionDbContext(DbContextOptions options) + : TestableDbContext(options) +{ + public DbSet Supermarkets => Set(); +} diff --git a/test/OpenApiTests/NamingConventions/OperationsController.cs b/test/OpenApiTests/NamingConventions/OperationsController.cs new file mode 100644 index 0000000000..c4c024c099 --- /dev/null +++ b/test/OpenApiTests/NamingConventions/OperationsController.cs @@ -0,0 +1,13 @@ +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.Resources; +using Microsoft.Extensions.Logging; + +namespace OpenApiTests.NamingConventions; + +public sealed class OperationsController( + IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, IOperationsProcessor processor, IJsonApiRequest request, + ITargetedFields targetedFields, IAtomicOperationFilter operationFilter) + : JsonApiOperationsController(options, resourceGraph, loggerFactory, processor, request, targetedFields, operationFilter); diff --git a/test/OpenApiTests/NamingConventions/PascalCase/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/NamingConventions/PascalCase/GeneratedSwagger/swagger.g.json new file mode 100644 index 0000000000..ad97782721 --- /dev/null +++ b/test/OpenApiTests/NamingConventions/PascalCase/GeneratedSwagger/swagger.g.json @@ -0,0 +1,5079 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "OpenApiTests", + "version": "1.0" + }, + "servers": [ + { + "url": "http://localhost" + } + ], + "paths": { + "/Operations": { + "post": { + "tags": [ + "operations" + ], + "summary": "Performs multiple mutations in a linear and atomic manner.", + "operationId": "PostOperations", + "requestBody": { + "description": "An array of mutation operations. For syntax, see the [Atomic Operations documentation](https://jsonapi.org/ext/atomic/).", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/OperationsRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "All operations were successfully applied, which resulted in additional changes.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/OperationsResponseDocument" + } + } + } + }, + "204": { + "description": "All operations were successfully applied, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "403": { + "description": "An operation is not accessible or a client-generated ID is used.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "404": { + "description": "A resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + } + } + } + }, + "/StaffMembers": { + "get": { + "tags": [ + "StaffMembers" + ], + "summary": "Retrieves a collection of StaffMembers.", + "operationId": "GetStaffMemberCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found StaffMembers, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/StaffMemberCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "StaffMembers" + ], + "summary": "Retrieves a collection of StaffMembers without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "HeadStaffMemberCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "StaffMembers" + ], + "summary": "Creates a new StaffMember.", + "operationId": "PostStaffMember", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the StaffMember to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/CreateStaffMemberRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The StaffMember was successfully created, which resulted in additional changes. The newly created StaffMember is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created StaffMember can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/PrimaryStaffMemberResponseDocument" + } + } + } + }, + "204": { + "description": "The StaffMember was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + } + } + } + }, + "/StaffMembers/{id}": { + "get": { + "tags": [ + "StaffMembers" + ], + "summary": "Retrieves an individual StaffMember by its identifier.", + "operationId": "GetStaffMember", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the StaffMember to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found StaffMember.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/PrimaryStaffMemberResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "404": { + "description": "The StaffMember does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "StaffMembers" + ], + "summary": "Retrieves an individual StaffMember by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "HeadStaffMember", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the StaffMember to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The StaffMember does not exist." + } + } + }, + "patch": { + "tags": [ + "StaffMembers" + ], + "summary": "Updates an existing StaffMember.", + "operationId": "PatchStaffMember", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the StaffMember to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the StaffMember to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/UpdateStaffMemberRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The StaffMember was successfully updated, which resulted in additional changes. The updated StaffMember is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/PrimaryStaffMemberResponseDocument" + } + } + } + }, + "204": { + "description": "The StaffMember was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "404": { + "description": "The StaffMember or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "StaffMembers" + ], + "summary": "Deletes an existing StaffMember by its identifier.", + "operationId": "DeleteStaffMember", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the StaffMember to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "responses": { + "204": { + "description": "The StaffMember was successfully deleted." + }, + "404": { + "description": "The StaffMember does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + } + } + } + }, + "/Supermarkets": { + "get": { + "tags": [ + "Supermarkets" + ], + "summary": "Retrieves a collection of Supermarkets.", + "operationId": "GetSupermarketCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found Supermarkets, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/SupermarketCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "Supermarkets" + ], + "summary": "Retrieves a collection of Supermarkets without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "HeadSupermarketCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "Supermarkets" + ], + "summary": "Creates a new Supermarket.", + "operationId": "PostSupermarket", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the Supermarket to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/CreateSupermarketRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The Supermarket was successfully created, which resulted in additional changes. The newly created Supermarket is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created Supermarket can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/PrimarySupermarketResponseDocument" + } + } + } + }, + "204": { + "description": "The Supermarket was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + } + } + } + }, + "/Supermarkets/{id}": { + "get": { + "tags": [ + "Supermarkets" + ], + "summary": "Retrieves an individual Supermarket by its identifier.", + "operationId": "GetSupermarket", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the Supermarket to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found Supermarket.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/PrimarySupermarketResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "404": { + "description": "The Supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "Supermarkets" + ], + "summary": "Retrieves an individual Supermarket by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "HeadSupermarket", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the Supermarket to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The Supermarket does not exist." + } + } + }, + "patch": { + "tags": [ + "Supermarkets" + ], + "summary": "Updates an existing Supermarket.", + "operationId": "PatchSupermarket", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the Supermarket to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the Supermarket to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/UpdateSupermarketRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The Supermarket was successfully updated, which resulted in additional changes. The updated Supermarket is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/PrimarySupermarketResponseDocument" + } + } + } + }, + "204": { + "description": "The Supermarket was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "404": { + "description": "The Supermarket or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "Supermarkets" + ], + "summary": "Deletes an existing Supermarket by its identifier.", + "operationId": "DeleteSupermarket", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the Supermarket to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "responses": { + "204": { + "description": "The Supermarket was successfully deleted." + }, + "404": { + "description": "The Supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + } + } + } + }, + "/Supermarkets/{id}/BackupStoreManager": { + "get": { + "tags": [ + "Supermarkets" + ], + "summary": "Retrieves the related StaffMember of an individual Supermarket's BackupStoreManager relationship.", + "operationId": "GetSupermarketBackupStoreManager", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the Supermarket whose related StaffMember to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found StaffMember, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/NullableSecondaryStaffMemberResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "404": { + "description": "The Supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "Supermarkets" + ], + "summary": "Retrieves the related StaffMember of an individual Supermarket's BackupStoreManager relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "HeadSupermarketBackupStoreManager", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the Supermarket whose related StaffMember to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The Supermarket does not exist." + } + } + } + }, + "/Supermarkets/{id}/relationships/BackupStoreManager": { + "get": { + "tags": [ + "Supermarkets" + ], + "summary": "Retrieves the related StaffMember identity of an individual Supermarket's BackupStoreManager relationship.", + "operationId": "GetSupermarketBackupStoreManagerRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the Supermarket whose related StaffMember identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found StaffMember identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/NullableStaffMemberIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "404": { + "description": "The Supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "Supermarkets" + ], + "summary": "Retrieves the related StaffMember identity of an individual Supermarket's BackupStoreManager relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "HeadSupermarketBackupStoreManagerRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the Supermarket whose related StaffMember identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The Supermarket does not exist." + } + } + }, + "patch": { + "tags": [ + "Supermarkets" + ], + "summary": "Clears or assigns an existing StaffMember to the BackupStoreManager relationship of an individual Supermarket.", + "operationId": "PatchSupermarketBackupStoreManagerRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the Supermarket whose BackupStoreManager relationship to assign or clear.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identity of the StaffMember to assign to the BackupStoreManager relationship, or `null` to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/NullableToOneStaffMemberInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The BackupStoreManager relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "404": { + "description": "The Supermarket or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + } + } + } + }, + "/Supermarkets/{id}/Cashiers": { + "get": { + "tags": [ + "Supermarkets" + ], + "summary": "Retrieves the related StaffMembers of an individual Supermarket's Cashiers relationship.", + "operationId": "GetSupermarketCashiers", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the Supermarket whose related StaffMembers to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found StaffMembers, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/StaffMemberCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "404": { + "description": "The Supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "Supermarkets" + ], + "summary": "Retrieves the related StaffMembers of an individual Supermarket's Cashiers relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "HeadSupermarketCashiers", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the Supermarket whose related StaffMembers to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The Supermarket does not exist." + } + } + } + }, + "/Supermarkets/{id}/relationships/Cashiers": { + "get": { + "tags": [ + "Supermarkets" + ], + "summary": "Retrieves the related StaffMember identities of an individual Supermarket's Cashiers relationship.", + "operationId": "GetSupermarketCashiersRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the Supermarket whose related StaffMember identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found StaffMember identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/StaffMemberIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "404": { + "description": "The Supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "Supermarkets" + ], + "summary": "Retrieves the related StaffMember identities of an individual Supermarket's Cashiers relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "HeadSupermarketCashiersRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the Supermarket whose related StaffMember identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The Supermarket does not exist." + } + } + }, + "post": { + "tags": [ + "Supermarkets" + ], + "summary": "Adds existing StaffMembers to the Cashiers relationship of an individual Supermarket.", + "operationId": "PostSupermarketCashiersRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the Supermarket to add StaffMembers to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the StaffMembers to add to the Cashiers relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/ToManyStaffMemberInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The StaffMembers were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "404": { + "description": "The Supermarket or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "Supermarkets" + ], + "summary": "Assigns existing StaffMembers to the Cashiers relationship of an individual Supermarket.", + "operationId": "PatchSupermarketCashiersRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the Supermarket whose Cashiers relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the StaffMembers to assign to the Cashiers relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/ToManyStaffMemberInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The Cashiers relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "404": { + "description": "The Supermarket or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "Supermarkets" + ], + "summary": "Removes existing StaffMembers from the Cashiers relationship of an individual Supermarket.", + "operationId": "DeleteSupermarketCashiersRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the Supermarket to remove StaffMembers from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the StaffMembers to remove from the Cashiers relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/ToManyStaffMemberInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The StaffMembers were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "404": { + "description": "The Supermarket or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + } + } + } + }, + "/Supermarkets/{id}/StoreManager": { + "get": { + "tags": [ + "Supermarkets" + ], + "summary": "Retrieves the related StaffMember of an individual Supermarket's StoreManager relationship.", + "operationId": "GetSupermarketStoreManager", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the Supermarket whose related StaffMember to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found StaffMember, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/SecondaryStaffMemberResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "404": { + "description": "The Supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "Supermarkets" + ], + "summary": "Retrieves the related StaffMember of an individual Supermarket's StoreManager relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "HeadSupermarketStoreManager", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the Supermarket whose related StaffMember to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The Supermarket does not exist." + } + } + } + }, + "/Supermarkets/{id}/relationships/StoreManager": { + "get": { + "tags": [ + "Supermarkets" + ], + "summary": "Retrieves the related StaffMember identity of an individual Supermarket's StoreManager relationship.", + "operationId": "GetSupermarketStoreManagerRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the Supermarket whose related StaffMember identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found StaffMember identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/StaffMemberIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "404": { + "description": "The Supermarket does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "Supermarkets" + ], + "summary": "Retrieves the related StaffMember identity of an individual Supermarket's StoreManager relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "HeadSupermarketStoreManagerRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the Supermarket whose related StaffMember identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The Supermarket does not exist." + } + } + }, + "patch": { + "tags": [ + "Supermarkets" + ], + "summary": "Assigns an existing StaffMember to the StoreManager relationship of an individual Supermarket.", + "operationId": "PatchSupermarketStoreManagerRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the Supermarket whose StoreManager relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identity of the StaffMember to assign to the StoreManager relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/ToOneStaffMemberInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The StoreManager relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "404": { + "description": "The Supermarket or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDocument" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "AddOperationCode": { + "enum": [ + "add" + ], + "type": "string" + }, + "AddToSupermarketCashiersRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/AtomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/AddOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/SupermarketCashiersRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/StaffMemberIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "AtomicOperation": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "type": "string" + }, + "Meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "AddStaffMember": "#/components/schemas/CreateStaffMemberOperation", + "AddSupermarket": "#/components/schemas/CreateSupermarketOperation", + "AddToSupermarketCashiers": "#/components/schemas/AddToSupermarketCashiersRelationshipOperation", + "RemoveFromSupermarketCashiers": "#/components/schemas/RemoveFromSupermarketCashiersRelationshipOperation", + "RemoveStaffMember": "#/components/schemas/DeleteStaffMemberOperation", + "RemoveSupermarket": "#/components/schemas/DeleteSupermarketOperation", + "UpdateStaffMember": "#/components/schemas/UpdateStaffMemberOperation", + "UpdateSupermarket": "#/components/schemas/UpdateSupermarketOperation", + "UpdateSupermarketBackupStoreManager": "#/components/schemas/UpdateSupermarketBackupStoreManagerRelationshipOperation", + "UpdateSupermarketCashiers": "#/components/schemas/UpdateSupermarketCashiersRelationshipOperation", + "UpdateSupermarketStoreManager": "#/components/schemas/UpdateSupermarketStoreManagerRelationshipOperation" + } + }, + "x-abstract": true + }, + "AtomicResult": { + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "AttributesInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "StaffMembers": "#/components/schemas/AttributesInCreateStaffMemberRequest", + "Supermarkets": "#/components/schemas/AttributesInCreateSupermarketRequest" + } + }, + "x-abstract": true + }, + "AttributesInCreateStaffMemberRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/AttributesInCreateRequest" + }, + { + "required": [ + "Name" + ], + "type": "object", + "properties": { + "Name": { + "type": "string" + }, + "Age": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "AttributesInCreateSupermarketRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/AttributesInCreateRequest" + }, + { + "required": [ + "NameOfCity" + ], + "type": "object", + "properties": { + "NameOfCity": { + "type": "string" + }, + "Kind": { + "allOf": [ + { + "$ref": "#/components/schemas/SupermarketType" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "AttributesInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "StaffMembers": "#/components/schemas/AttributesInStaffMemberResponse", + "Supermarkets": "#/components/schemas/AttributesInSupermarketResponse" + } + }, + "x-abstract": true + }, + "AttributesInStaffMemberResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/AttributesInResponse" + }, + { + "type": "object", + "properties": { + "Name": { + "type": "string" + }, + "Age": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "AttributesInSupermarketResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/AttributesInResponse" + }, + { + "type": "object", + "properties": { + "NameOfCity": { + "type": "string" + }, + "Kind": { + "allOf": [ + { + "$ref": "#/components/schemas/SupermarketType" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "AttributesInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "StaffMembers": "#/components/schemas/AttributesInUpdateStaffMemberRequest", + "Supermarkets": "#/components/schemas/AttributesInUpdateSupermarketRequest" + } + }, + "x-abstract": true + }, + "AttributesInUpdateStaffMemberRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/AttributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "Name": { + "type": "string" + }, + "Age": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "AttributesInUpdateSupermarketRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/AttributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "NameOfCity": { + "type": "string" + }, + "Kind": { + "allOf": [ + { + "$ref": "#/components/schemas/SupermarketType" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "CreateStaffMemberOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/AtomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/AddOperationCode" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/DataInCreateStaffMemberRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "CreateStaffMemberRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/DataInCreateStaffMemberRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "CreateSupermarketOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/AtomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/AddOperationCode" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/DataInCreateSupermarketRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "CreateSupermarketRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/DataInCreateSupermarketRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "DataInCreateStaffMemberRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/ResourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/AttributesInCreateStaffMemberRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "DataInCreateSupermarketRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/ResourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/AttributesInCreateSupermarketRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/RelationshipsInCreateSupermarketRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "DataInStaffMemberResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/AttributesInStaffMemberResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "DataInSupermarketResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/AttributesInSupermarketResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/RelationshipsInSupermarketResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "DataInUpdateStaffMemberRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/ResourceInUpdateRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/AttributesInUpdateStaffMemberRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "DataInUpdateSupermarketRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/ResourceInUpdateRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/AttributesInUpdateSupermarketRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/RelationshipsInUpdateSupermarketRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "DeleteStaffMemberOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/AtomicOperation" + }, + { + "required": [ + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/RemoveOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/StaffMemberIdentifierInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "DeleteSupermarketOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/AtomicOperation" + }, + { + "required": [ + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/RemoveOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/SupermarketIdentifierInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "ErrorLinks": { + "type": "object", + "properties": { + "about": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "ErrorObject": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/ErrorLinks" + } + ], + "nullable": true + }, + "status": { + "type": "string" + }, + "code": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/ErrorSource" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "ErrorResponseDocument": { + "required": [ + "errors", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/Jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/ErrorTopLevelLinks" + } + ] + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ErrorObject" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "ErrorSource": { + "type": "object", + "properties": { + "pointer": { + "type": "string", + "nullable": true + }, + "parameter": { + "type": "string", + "nullable": true + }, + "header": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "ErrorTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "IdentifierInRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceType" + } + ] + }, + "Meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "StaffMembers": "#/components/schemas/StaffMemberIdentifierInRequest", + "Supermarkets": "#/components/schemas/SupermarketIdentifierInRequest" + } + }, + "x-abstract": true + }, + "Jsonapi": { + "type": "object", + "properties": { + "version": { + "type": "string" + }, + "ext": { + "type": "array", + "items": { + "type": "string" + } + }, + "profile": { + "type": "array", + "items": { + "type": "string" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "Meta": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "NullableSecondaryStaffMemberResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/Jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/DataInStaffMemberResponse" + } + ], + "nullable": true + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ResourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "NullableStaffMemberIdentifierResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/Jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceIdentifierTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/StaffMemberIdentifierInResponse" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "NullableToOneStaffMemberInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/StaffMemberIdentifierInRequest" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "NullableToOneStaffMemberInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/RelationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/StaffMemberIdentifierInResponse" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "OperationsRequestDocument": { + "required": [ + "atomic:operations" + ], + "type": "object", + "properties": { + "atomic:operations": { + "minItems": 1, + "type": "array", + "items": { + "$ref": "#/components/schemas/AtomicOperation" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "OperationsResponseDocument": { + "required": [ + "atomic:results", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/Jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceTopLevelLinks" + } + ] + }, + "atomic:results": { + "minItems": 1, + "type": "array", + "items": { + "$ref": "#/components/schemas/AtomicResult" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "PrimaryStaffMemberResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/Jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/DataInStaffMemberResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ResourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "PrimarySupermarketResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/Jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/DataInSupermarketResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ResourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "RelationshipLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + } + }, + "additionalProperties": false + }, + "RelationshipsInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "Supermarkets": "#/components/schemas/RelationshipsInCreateSupermarketRequest" + } + }, + "x-abstract": true + }, + "RelationshipsInCreateSupermarketRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/RelationshipsInCreateRequest" + }, + { + "required": [ + "StoreManager" + ], + "type": "object", + "properties": { + "StoreManager": { + "allOf": [ + { + "$ref": "#/components/schemas/ToOneStaffMemberInRequest" + } + ] + }, + "BackupStoreManager": { + "allOf": [ + { + "$ref": "#/components/schemas/NullableToOneStaffMemberInRequest" + } + ] + }, + "Cashiers": { + "allOf": [ + { + "$ref": "#/components/schemas/ToManyStaffMemberInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "RelationshipsInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "Supermarkets": "#/components/schemas/RelationshipsInSupermarketResponse" + } + }, + "x-abstract": true + }, + "RelationshipsInSupermarketResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/RelationshipsInResponse" + }, + { + "type": "object", + "properties": { + "StoreManager": { + "allOf": [ + { + "$ref": "#/components/schemas/ToOneStaffMemberInResponse" + } + ] + }, + "BackupStoreManager": { + "allOf": [ + { + "$ref": "#/components/schemas/NullableToOneStaffMemberInResponse" + } + ] + }, + "Cashiers": { + "allOf": [ + { + "$ref": "#/components/schemas/ToManyStaffMemberInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "RelationshipsInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "Supermarkets": "#/components/schemas/RelationshipsInUpdateSupermarketRequest" + } + }, + "x-abstract": true + }, + "RelationshipsInUpdateSupermarketRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/RelationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "StoreManager": { + "allOf": [ + { + "$ref": "#/components/schemas/ToOneStaffMemberInRequest" + } + ] + }, + "BackupStoreManager": { + "allOf": [ + { + "$ref": "#/components/schemas/NullableToOneStaffMemberInRequest" + } + ] + }, + "Cashiers": { + "allOf": [ + { + "$ref": "#/components/schemas/ToManyStaffMemberInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "RemoveFromSupermarketCashiersRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/AtomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/RemoveOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/SupermarketCashiersRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/StaffMemberIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "RemoveOperationCode": { + "enum": [ + "remove" + ], + "type": "string" + }, + "ResourceCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "ResourceIdentifierCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "ResourceIdentifierTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "ResourceInCreateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceType" + } + ] + }, + "Meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "StaffMembers": "#/components/schemas/DataInCreateStaffMemberRequest", + "Supermarkets": "#/components/schemas/DataInCreateSupermarketRequest" + } + }, + "x-abstract": true + }, + "ResourceInResponse": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceType" + } + ] + }, + "Meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "StaffMembers": "#/components/schemas/DataInStaffMemberResponse", + "Supermarkets": "#/components/schemas/DataInSupermarketResponse" + } + }, + "x-abstract": true + }, + "ResourceInUpdateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceType" + } + ] + }, + "Meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "StaffMembers": "#/components/schemas/DataInUpdateStaffMemberRequest", + "Supermarkets": "#/components/schemas/DataInUpdateSupermarketRequest" + } + }, + "x-abstract": true + }, + "ResourceLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + }, + "additionalProperties": false + }, + "ResourceTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "ResourceType": { + "enum": [ + "StaffMembers", + "Supermarkets" + ], + "type": "string" + }, + "SecondaryStaffMemberResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/Jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/DataInStaffMemberResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ResourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "StaffMemberCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/Jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DataInStaffMemberResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ResourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "StaffMemberIdentifierCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/Jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceIdentifierCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/StaffMemberIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "StaffMemberIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/IdentifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "StaffMemberIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/StaffMemberResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "StaffMemberIdentifierResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/Jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceIdentifierTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/StaffMemberIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "StaffMemberResourceType": { + "enum": [ + "StaffMembers" + ], + "type": "string" + }, + "SupermarketBackupStoreManagerRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/SupermarketResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/SupermarketBackupStoreManagerRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "SupermarketBackupStoreManagerRelationshipName": { + "enum": [ + "BackupStoreManager" + ], + "type": "string" + }, + "SupermarketCashiersRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/SupermarketResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/SupermarketCashiersRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "SupermarketCashiersRelationshipName": { + "enum": [ + "Cashiers" + ], + "type": "string" + }, + "SupermarketCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "jsonapi": { + "allOf": [ + { + "$ref": "#/components/schemas/Jsonapi" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/ResourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DataInSupermarketResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ResourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "SupermarketIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/IdentifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "SupermarketResourceType": { + "enum": [ + "Supermarkets" + ], + "type": "string" + }, + "SupermarketStoreManagerRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/SupermarketResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/SupermarketStoreManagerRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "SupermarketStoreManagerRelationshipName": { + "enum": [ + "StoreManager" + ], + "type": "string" + }, + "SupermarketType": { + "enum": [ + "Traditional", + "Budget", + "Warehouse" + ], + "type": "string" + }, + "ToManyStaffMemberInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/StaffMemberIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "ToManyStaffMemberInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/RelationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/StaffMemberIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "ToOneStaffMemberInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/StaffMemberIdentifierInRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "ToOneStaffMemberInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/RelationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/StaffMemberIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "UpdateOperationCode": { + "enum": [ + "update" + ], + "type": "string" + }, + "UpdateStaffMemberOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/AtomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/UpdateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/StaffMemberIdentifierInRequest" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/DataInUpdateStaffMemberRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "UpdateStaffMemberRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/DataInUpdateStaffMemberRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "UpdateSupermarketBackupStoreManagerRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/AtomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/UpdateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/SupermarketBackupStoreManagerRelationshipIdentifier" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/StaffMemberIdentifierInRequest" + } + ], + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "UpdateSupermarketCashiersRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/AtomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/UpdateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/SupermarketCashiersRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/StaffMemberIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "UpdateSupermarketOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/AtomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/UpdateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/SupermarketIdentifierInRequest" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/DataInUpdateSupermarketRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "UpdateSupermarketRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/DataInUpdateSupermarketRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/Meta" + } + ] + } + }, + "additionalProperties": false + }, + "UpdateSupermarketStoreManagerRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/AtomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/UpdateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/SupermarketStoreManagerRelationshipIdentifier" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/StaffMemberIdentifierInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/test/OpenApiTests/NamingConventions/PascalCase/PascalCaseNamingConventionStartup.cs b/test/OpenApiTests/NamingConventions/PascalCase/PascalCaseNamingConventionStartup.cs new file mode 100644 index 0000000000..8a367641f2 --- /dev/null +++ b/test/OpenApiTests/NamingConventions/PascalCase/PascalCaseNamingConventionStartup.cs @@ -0,0 +1,21 @@ +using System.Text.Json.Serialization; +using JetBrains.Annotations; +using JsonApiDotNetCore.Configuration; +using TestBuildingBlocks; + +namespace OpenApiTests.NamingConventions.PascalCase; + +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +public sealed class PascalCaseNamingConventionStartup : OpenApiStartup + where TDbContext : TestableDbContext +{ + protected override void SetJsonApiOptions(JsonApiOptions options) + { + base.SetJsonApiOptions(options); + + options.IncludeJsonApiVersion = true; + options.SerializerOptions.PropertyNamingPolicy = null; + options.SerializerOptions.DictionaryKeyPolicy = null; + options.SerializerOptions.Converters.Add(new JsonStringEnumConverter()); + } +} diff --git a/test/OpenApiTests/NamingConventions/PascalCase/PascalCaseTests.cs b/test/OpenApiTests/NamingConventions/PascalCase/PascalCaseTests.cs new file mode 100644 index 0000000000..fb5405e6f6 --- /dev/null +++ b/test/OpenApiTests/NamingConventions/PascalCase/PascalCaseTests.cs @@ -0,0 +1,685 @@ +using System.Text.Json; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.NamingConventions.PascalCase; + +public sealed class PascalCaseTests : IClassFixture, NamingConventionDbContext>> +{ + private const string EscapedJsonApiMediaType = "['application/vnd.api+json; ext=openapi']"; + private const string EscapedOperationsMediaType = "['application/vnd.api+json; ext=atomic; ext=openapi']"; + + private readonly OpenApiTestContext, NamingConventionDbContext> _testContext; + + public PascalCaseTests(OpenApiTestContext, NamingConventionDbContext> testContext, + ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + + testContext.SetTestOutputHelper(testOutputHelper); + testContext.SwaggerDocumentOutputDirectory = $"{GetType().Namespace!.Replace('.', '/')}/GeneratedSwagger"; + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetCollection_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + string? documentSchemaRefId = null; + + document.Should().ContainPath("paths./Supermarkets.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("GetSupermarketCollection"); + }); + + documentSchemaRefId = getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("SupermarketCollectionResponseDocument").SchemaReferenceId; + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + string? topLevelLinksSchemaRefId = null; + string? resourceDataSchemaRefId = null; + + schemasElement.Should().ContainPath($"{documentSchemaRefId}.properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("jsonapi.allOf[0].$ref").ShouldBeSchemaReferenceId("Jsonapi"); + + topLevelLinksSchemaRefId = propertiesElement.Should().ContainPath("links.allOf[0].$ref") + .ShouldBeSchemaReferenceId("ResourceCollectionTopLevelLinks").SchemaReferenceId; + + resourceDataSchemaRefId = propertiesElement.Should().ContainPath("data.items.$ref").ShouldBeSchemaReferenceId("DataInSupermarketResponse") + .SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{topLevelLinksSchemaRefId}.properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("self"); + propertiesElement.Should().ContainProperty("describedby"); + propertiesElement.Should().ContainProperty("first"); + propertiesElement.Should().ContainProperty("last"); + propertiesElement.Should().ContainProperty("prev"); + propertiesElement.Should().ContainProperty("next"); + }); + + string? resourceLinksSchemaRefId = null; + string? resourceAttributesInResponseSchemaRefId = null; + string? resourceRelationshipInResponseSchemaRefId = null; + + string abstractResourceDataSchemaRefId = schemasElement.Should().ContainPath($"{resourceDataSchemaRefId}.allOf[0].$ref") + .ShouldBeSchemaReferenceId("ResourceInResponse").SchemaReferenceId; + + schemasElement.Should().ContainPath($"{abstractResourceDataSchemaRefId}.discriminator.mapping").With(mappingElement => + { + mappingElement.Should().ContainPath("Supermarkets").ShouldBeSchemaReferenceId("DataInSupermarketResponse"); + mappingElement.Should().ContainPath("StaffMembers").ShouldBeSchemaReferenceId("DataInStaffMemberResponse"); + }); + + schemasElement.Should().ContainPath($"{resourceDataSchemaRefId}.allOf[1].properties").With(propertiesElement => + { + resourceLinksSchemaRefId = propertiesElement.Should().ContainPath("links.allOf[0].$ref").ShouldBeSchemaReferenceId("ResourceLinks") + .SchemaReferenceId; + + resourceAttributesInResponseSchemaRefId = propertiesElement.Should().ContainPath("attributes.allOf[0].$ref") + .ShouldBeSchemaReferenceId("AttributesInSupermarketResponse").SchemaReferenceId; + + resourceRelationshipInResponseSchemaRefId = propertiesElement.Should().ContainPath("relationships.allOf[0].$ref") + .ShouldBeSchemaReferenceId("RelationshipsInSupermarketResponse").SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{resourceLinksSchemaRefId}.properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("self"); + }); + + schemasElement.Should().ContainPath($"{resourceAttributesInResponseSchemaRefId}.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("NameOfCity"); + propertiesElement.Should().ContainProperty("Kind"); + propertiesElement.Should().ContainPath("Kind.allOf[0].$ref").ShouldBeSchemaReferenceId("SupermarketType"); + }); + + string? nullableToOneResourceResponseDataSchemaRefId = null; + + schemasElement.Should().ContainPath($"{resourceRelationshipInResponseSchemaRefId}.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("StoreManager"); + + propertiesElement.Should().ContainPath("StoreManager.allOf[0].$ref").ShouldBeSchemaReferenceId("ToOneStaffMemberInResponse"); + + nullableToOneResourceResponseDataSchemaRefId = propertiesElement.Should().ContainPath("BackupStoreManager.allOf[0].$ref") + .ShouldBeSchemaReferenceId("NullableToOneStaffMemberInResponse").SchemaReferenceId; + + propertiesElement.Should().ContainProperty("Cashiers"); + propertiesElement.Should().ContainPath("Cashiers.allOf[0].$ref").ShouldBeSchemaReferenceId("ToManyStaffMemberInResponse"); + }); + + string? relationshipLinksSchemaRefId = null; + string? relatedResourceIdentifierSchemaRefId = null; + + schemasElement.Should().ContainPath($"{nullableToOneResourceResponseDataSchemaRefId}.properties").With(propertiesElement => + { + relationshipLinksSchemaRefId = propertiesElement.Should().ContainPath("links.allOf[0].$ref").ShouldBeSchemaReferenceId("RelationshipLinks") + .SchemaReferenceId; + + relatedResourceIdentifierSchemaRefId = propertiesElement.Should().ContainPath("data.allOf[0].$ref") + .ShouldBeSchemaReferenceId("StaffMemberIdentifierInResponse").SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{relationshipLinksSchemaRefId}.properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("self"); + propertiesElement.Should().ContainProperty("related"); + }); + + string? relatedResourceTypeSchemaRefId = null; + + schemasElement.Should().ContainPath($"{relatedResourceIdentifierSchemaRefId}.properties").With(propertiesElement => + { + relatedResourceTypeSchemaRefId = propertiesElement.Should().ContainPath("type.allOf[0].$ref") + .ShouldBeSchemaReferenceId("StaffMemberResourceType").SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{relatedResourceTypeSchemaRefId}.enum").With(codeElement => + { + codeElement.Should().ContainArrayElement("StaffMembers"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetSingle_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + string? documentSchemaRefId = null; + + document.Should().ContainPath("paths./Supermarkets/{id}.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("GetSupermarket"); + }); + + documentSchemaRefId = getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("PrimarySupermarketResponseDocument").SchemaReferenceId; + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + string? topLevelLinksSchemaRefId = null; + + schemasElement.Should().ContainPath($"{documentSchemaRefId}.properties").With(propertiesElement => + { + topLevelLinksSchemaRefId = propertiesElement.Should().ContainPath("links.allOf[0].$ref").ShouldBeSchemaReferenceId("ResourceTopLevelLinks") + .SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{topLevelLinksSchemaRefId}.properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("self"); + propertiesElement.Should().ContainProperty("describedby"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetSecondary_endpoint_with_single_resource() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + string? documentSchemaRefId = null; + + document.Should().ContainPath("paths./Supermarkets/{id}/StoreManager.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("GetSupermarketStoreManager"); + }); + + documentSchemaRefId = getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("SecondaryStaffMemberResponseDocument").SchemaReferenceId; + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + string? resourceDataSchemaRefId = null; + + schemasElement.Should().ContainPath($"{documentSchemaRefId}.properties").With(propertiesElement => + { + resourceDataSchemaRefId = propertiesElement.Should().ContainPath("data.allOf[0].$ref").ShouldBeSchemaReferenceId("DataInStaffMemberResponse") + .SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{resourceDataSchemaRefId}.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("attributes.allOf[0].$ref").ShouldBeSchemaReferenceId("AttributesInStaffMemberResponse"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetSecondary_endpoint_with_nullable_resource() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./Supermarkets/{id}/BackupStoreManager.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("GetSupermarketBackupStoreManager"); + }); + + getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("NullableSecondaryStaffMemberResponseDocument"); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetSecondary_endpoint_with_resources() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./Supermarkets/{id}/Cashiers.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("GetSupermarketCashiers"); + }); + + getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("StaffMemberCollectionResponseDocument"); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetRelationship_endpoint_with_ToOne_relationship() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + string? documentSchemaRefId = null; + + document.Should().ContainPath("paths./Supermarkets/{id}/relationships/StoreManager.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("GetSupermarketStoreManagerRelationship"); + }); + + documentSchemaRefId = getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("StaffMemberIdentifierResponseDocument").SchemaReferenceId; + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + string? topLevelLinksSchemaRefId = null; + + schemasElement.Should().ContainPath($"{documentSchemaRefId}.properties").With(propertiesElement => + { + topLevelLinksSchemaRefId = propertiesElement.Should().ContainPath("links.allOf[0].$ref") + .ShouldBeSchemaReferenceId("ResourceIdentifierTopLevelLinks").SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{topLevelLinksSchemaRefId}.properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("self"); + propertiesElement.Should().ContainProperty("describedby"); + propertiesElement.Should().ContainProperty("related"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetRelationship_endpoint_with_nullable_ToOne_relationship() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./Supermarkets/{id}/relationships/BackupStoreManager.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("GetSupermarketBackupStoreManagerRelationship"); + }); + + getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("NullableStaffMemberIdentifierResponseDocument"); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_GetRelationship_endpoint_with_ToMany_relationship() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + string? documentSchemaRefId = null; + + document.Should().ContainPath("paths./Supermarkets/{id}/relationships/Cashiers.get").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("GetSupermarketCashiersRelationship"); + }); + + documentSchemaRefId = getElement.Should().ContainPath($"responses.200.content{EscapedJsonApiMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("StaffMemberIdentifierCollectionResponseDocument").SchemaReferenceId; + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + string? topLevelLinksSchemaRefId = null; + + schemasElement.Should().ContainPath($"{documentSchemaRefId}.properties").With(propertiesElement => + { + topLevelLinksSchemaRefId = propertiesElement.Should().ContainPath("links.allOf[0].$ref") + .ShouldBeSchemaReferenceId("ResourceIdentifierCollectionTopLevelLinks").SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{topLevelLinksSchemaRefId}.properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("self"); + propertiesElement.Should().ContainProperty("describedby"); + propertiesElement.Should().ContainProperty("related"); + propertiesElement.Should().ContainProperty("first"); + propertiesElement.Should().ContainProperty("last"); + propertiesElement.Should().ContainProperty("prev"); + propertiesElement.Should().ContainProperty("next"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_Post_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + string? documentSchemaRefId = null; + + document.Should().ContainPath("paths./Supermarkets.post").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("PostSupermarket"); + }); + + documentSchemaRefId = getElement.Should().ContainPath($"requestBody.content{EscapedJsonApiMediaType}.schema.allOf[0].$ref") + .ShouldBeSchemaReferenceId("CreateSupermarketRequestDocument").SchemaReferenceId; + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + string? resourceDataSchemaRefId = null; + + schemasElement.Should().ContainPath($"{documentSchemaRefId}.properties").With(propertiesElement => + { + resourceDataSchemaRefId = propertiesElement.Should().ContainPath("data.allOf[0].$ref") + .ShouldBeSchemaReferenceId("DataInCreateSupermarketRequest").SchemaReferenceId; + }); + + string? resourceRelationshipInPostRequestSchemaRefId = null; + + schemasElement.Should().ContainPath($"{resourceDataSchemaRefId}.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("attributes.allOf[0].$ref").ShouldBeSchemaReferenceId("AttributesInCreateSupermarketRequest"); + + resourceRelationshipInPostRequestSchemaRefId = propertiesElement.Should().ContainPath("relationships.allOf[0].$ref") + .ShouldBeSchemaReferenceId("RelationshipsInCreateSupermarketRequest").SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{resourceRelationshipInPostRequestSchemaRefId}.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainProperty("StoreManager"); + propertiesElement.Should().ContainPath("StoreManager.allOf[0].$ref").ShouldBeSchemaReferenceId("ToOneStaffMemberInRequest"); + + propertiesElement.Should().ContainProperty("BackupStoreManager"); + propertiesElement.Should().ContainPath("BackupStoreManager.allOf[0].$ref").ShouldBeSchemaReferenceId("NullableToOneStaffMemberInRequest"); + + propertiesElement.Should().ContainProperty("Cashiers"); + propertiesElement.Should().ContainPath("Cashiers.allOf[0].$ref").ShouldBeSchemaReferenceId("ToManyStaffMemberInRequest"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_PostRelationship_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./Supermarkets/{id}/relationships/Cashiers.post").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("PostSupermarketCashiersRelationship"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_Patch_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + string? documentSchemaRefId = null; + + document.Should().ContainPath("paths./Supermarkets/{id}.patch").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("PatchSupermarket"); + }); + + documentSchemaRefId = getElement.Should().ContainPath($"requestBody.content{EscapedJsonApiMediaType}.schema.allOf[0].$ref") + .ShouldBeSchemaReferenceId("UpdateSupermarketRequestDocument").SchemaReferenceId; + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + string? resourceDataSchemaRefId = null; + + schemasElement.Should().ContainPath($"{documentSchemaRefId}.properties").With(propertiesElement => + { + resourceDataSchemaRefId = propertiesElement.Should().ContainPath("data.allOf[0].$ref") + .ShouldBeSchemaReferenceId("DataInUpdateSupermarketRequest").SchemaReferenceId; + }); + + schemasElement.Should().ContainPath($"{resourceDataSchemaRefId}.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("attributes.allOf[0].$ref").ShouldBeSchemaReferenceId("AttributesInUpdateSupermarketRequest"); + propertiesElement.Should().ContainPath("relationships.allOf[0].$ref").ShouldBeSchemaReferenceId("RelationshipsInUpdateSupermarketRequest"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_PatchRelationship_endpoint_with_ToOne_relationship() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./Supermarkets/{id}/relationships/StoreManager.patch").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("PatchSupermarketStoreManagerRelationship"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_PatchRelationship_endpoint_with_nullable_ToOne_relationship() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./Supermarkets/{id}/relationships/BackupStoreManager.patch").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("PatchSupermarketBackupStoreManagerRelationship"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_PatchRelationship_endpoint_with_ToMany_relationship() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./Supermarkets/{id}/relationships/Cashiers.patch").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("PatchSupermarketCashiersRelationship"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_Delete_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./Supermarkets/{id}.delete").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("DeleteSupermarket"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_DeleteRelationship_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./Supermarkets/{id}/relationships/Cashiers.delete").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("DeleteSupermarketCashiersRelationship"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_PostOperations_endpoint() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("paths./Operations.post").With(getElement => + { + getElement.Should().ContainPath("operationId").With(operationElement => + { + operationElement.Should().Be("PostOperations"); + }); + + getElement.Should().ContainPath($"requestBody.content{EscapedOperationsMediaType}.schema.allOf[0].$ref") + .ShouldBeSchemaReferenceId("OperationsRequestDocument"); + + getElement.Should().ContainPath($"responses.200.content{EscapedOperationsMediaType}.schema.$ref") + .ShouldBeSchemaReferenceId("OperationsResponseDocument"); + }); + + document.Should().ContainPath("components.schemas").With(schemasElement => + { + schemasElement.Should().ContainPath("AddOperationCode.enum").With(codeElement => codeElement.Should().ContainArrayElement("add")); + schemasElement.Should().ContainPath("UpdateOperationCode.enum").With(codeElement => codeElement.Should().ContainArrayElement("update")); + schemasElement.Should().ContainPath("RemoveOperationCode.enum").With(codeElement => codeElement.Should().ContainArrayElement("remove")); + + schemasElement.Should().ContainPath("AtomicOperation.discriminator.mapping").With(mappingElement => + { + mappingElement.Should().ContainPath("AddStaffMember").ShouldBeSchemaReferenceId("CreateStaffMemberOperation"); + mappingElement.Should().ContainPath("AddSupermarket").ShouldBeSchemaReferenceId("CreateSupermarketOperation"); + mappingElement.Should().ContainPath("AddToSupermarketCashiers").ShouldBeSchemaReferenceId("AddToSupermarketCashiersRelationshipOperation"); + + mappingElement.Should().ContainPath("RemoveFromSupermarketCashiers") + .ShouldBeSchemaReferenceId("RemoveFromSupermarketCashiersRelationshipOperation"); + + mappingElement.Should().ContainPath("RemoveStaffMember").ShouldBeSchemaReferenceId("DeleteStaffMemberOperation"); + mappingElement.Should().ContainPath("RemoveSupermarket").ShouldBeSchemaReferenceId("DeleteSupermarketOperation"); + mappingElement.Should().ContainPath("UpdateStaffMember").ShouldBeSchemaReferenceId("UpdateStaffMemberOperation"); + mappingElement.Should().ContainPath("UpdateSupermarket").ShouldBeSchemaReferenceId("UpdateSupermarketOperation"); + + mappingElement.Should().ContainPath("UpdateSupermarketBackupStoreManager") + .ShouldBeSchemaReferenceId("UpdateSupermarketBackupStoreManagerRelationshipOperation"); + + mappingElement.Should().ContainPath("UpdateSupermarketCashiers").ShouldBeSchemaReferenceId("UpdateSupermarketCashiersRelationshipOperation"); + + mappingElement.Should().ContainPath("UpdateSupermarketStoreManager") + .ShouldBeSchemaReferenceId("UpdateSupermarketStoreManagerRelationshipOperation"); + }); + + schemasElement.Should().ContainPath("CreateSupermarketOperation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("data.allOf[0].$ref").ShouldBeSchemaReferenceId("DataInCreateSupermarketRequest"); + }); + + schemasElement.Should().ContainPath("UpdateSupermarketOperation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("SupermarketIdentifierInRequest"); + propertiesElement.Should().ContainPath("data.allOf[0].$ref").ShouldBeSchemaReferenceId("DataInUpdateSupermarketRequest"); + }); + + schemasElement.Should().ContainPath("DeleteSupermarketOperation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("SupermarketIdentifierInRequest"); + }); + + schemasElement.Should().ContainPath("UpdateSupermarketStoreManagerRelationshipOperation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("SupermarketStoreManagerRelationshipIdentifier"); + propertiesElement.Should().ContainPath("data.allOf[0].$ref").ShouldBeSchemaReferenceId("StaffMemberIdentifierInRequest"); + }); + + schemasElement.Should().ContainPath("UpdateSupermarketBackupStoreManagerRelationshipOperation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("SupermarketBackupStoreManagerRelationshipIdentifier"); + propertiesElement.Should().ContainPath("data.allOf[0].$ref").ShouldBeSchemaReferenceId("StaffMemberIdentifierInRequest"); + }); + + schemasElement.Should().ContainPath("UpdateSupermarketCashiersRelationshipOperation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("SupermarketCashiersRelationshipIdentifier"); + propertiesElement.Should().ContainPath("data.items.$ref").ShouldBeSchemaReferenceId("StaffMemberIdentifierInRequest"); + }); + + schemasElement.Should().ContainPath("AddToSupermarketCashiersRelationshipOperation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("SupermarketCashiersRelationshipIdentifier"); + propertiesElement.Should().ContainPath("data.items.$ref").ShouldBeSchemaReferenceId("StaffMemberIdentifierInRequest"); + }); + + schemasElement.Should().ContainPath("RemoveFromSupermarketCashiersRelationshipOperation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("SupermarketCashiersRelationshipIdentifier"); + propertiesElement.Should().ContainPath("data.items.$ref").ShouldBeSchemaReferenceId("StaffMemberIdentifierInRequest"); + }); + + schemasElement.Should().ContainPath("CreateStaffMemberOperation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("data.allOf[0].$ref").ShouldBeSchemaReferenceId("DataInCreateStaffMemberRequest"); + }); + + schemasElement.Should().ContainPath("UpdateStaffMemberOperation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("StaffMemberIdentifierInRequest"); + propertiesElement.Should().ContainPath("data.allOf[0].$ref").ShouldBeSchemaReferenceId("DataInUpdateStaffMemberRequest"); + }); + + schemasElement.Should().ContainPath("DeleteStaffMemberOperation.allOf[1].properties").With(propertiesElement => + { + propertiesElement.Should().ContainPath("ref.allOf[0].$ref").ShouldBeSchemaReferenceId("StaffMemberIdentifierInRequest"); + }); + }); + } + + [Fact] + public async Task Casing_convention_is_applied_to_error_schema() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.ErrorResponseDocument"); + document.Should().ContainPath("components.schemas.ErrorTopLevelLinks"); + } +} diff --git a/test/OpenApiTests/NamingConventions/StaffMember.cs b/test/OpenApiTests/NamingConventions/StaffMember.cs new file mode 100644 index 0000000000..b2df548a17 --- /dev/null +++ b/test/OpenApiTests/NamingConventions/StaffMember.cs @@ -0,0 +1,16 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.NamingConventions; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.NamingConventions")] +public sealed class StaffMember : Identifiable +{ + [Attr] + public string Name { get; set; } = null!; + + [Attr] + public int Age { get; set; } +} diff --git a/test/OpenApiTests/NamingConventions/Supermarket.cs b/test/OpenApiTests/NamingConventions/Supermarket.cs new file mode 100644 index 0000000000..4bde8776da --- /dev/null +++ b/test/OpenApiTests/NamingConventions/Supermarket.cs @@ -0,0 +1,25 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.NamingConventions; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.NamingConventions")] +public sealed class Supermarket : Identifiable +{ + [Attr] + public string NameOfCity { get; set; } = null!; + + [Attr] + public SupermarketType Kind { get; set; } + + [HasOne] + public StaffMember StoreManager { get; set; } = null!; + + [HasOne] + public StaffMember? BackupStoreManager { get; set; } + + [HasMany] + public ICollection Cashiers { get; set; } = new HashSet(); +} diff --git a/test/OpenApiTests/NamingConventions/SupermarketType.cs b/test/OpenApiTests/NamingConventions/SupermarketType.cs new file mode 100644 index 0000000000..45570936f5 --- /dev/null +++ b/test/OpenApiTests/NamingConventions/SupermarketType.cs @@ -0,0 +1,11 @@ +using JetBrains.Annotations; + +namespace OpenApiTests.NamingConventions; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public enum SupermarketType +{ + Traditional, + Budget, + Warehouse +} diff --git a/test/OpenApiTests/OpenApiGenerationFailures/MissingFromBody/MissingFromBodyDbContext.cs b/test/OpenApiTests/OpenApiGenerationFailures/MissingFromBody/MissingFromBodyDbContext.cs new file mode 100644 index 0000000000..b9805fc669 --- /dev/null +++ b/test/OpenApiTests/OpenApiGenerationFailures/MissingFromBody/MissingFromBodyDbContext.cs @@ -0,0 +1,12 @@ +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; +using TestBuildingBlocks; + +namespace OpenApiTests.OpenApiGenerationFailures.MissingFromBody; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public sealed class MissingFromBodyDbContext(DbContextOptions options) + : TestableDbContext(options) +{ + public DbSet RecycleBins => Set(); +} diff --git a/test/OpenApiTests/OpenApiGenerationFailures/MissingFromBody/MissingFromBodyOnPatchController.cs b/test/OpenApiTests/OpenApiGenerationFailures/MissingFromBody/MissingFromBodyOnPatchController.cs new file mode 100644 index 0000000000..69f117c619 --- /dev/null +++ b/test/OpenApiTests/OpenApiGenerationFailures/MissingFromBody/MissingFromBodyOnPatchController.cs @@ -0,0 +1,20 @@ +using System.ComponentModel.DataAnnotations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Services; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; + +namespace OpenApiTests.OpenApiGenerationFailures.MissingFromBody; + +public sealed class MissingFromBodyOnPatchController( + IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, IResourceService resourceService) + : BaseJsonApiController(options, resourceGraph, loggerFactory, resourceService) +{ + // Not overriding the base method, to trigger the error that [FromBody] is missing. + [HttpPatch("{id}")] + public Task AlternatePatchAsync([Required] long id, [Required] RecycleBin resource, CancellationToken cancellationToken) + { + return PatchAsync(id, resource, cancellationToken); + } +} diff --git a/test/OpenApiTests/OpenApiGenerationFailures/MissingFromBody/MissingFromBodyOnPatchMethodTests.cs b/test/OpenApiTests/OpenApiGenerationFailures/MissingFromBody/MissingFromBodyOnPatchMethodTests.cs new file mode 100644 index 0000000000..20814f2f80 --- /dev/null +++ b/test/OpenApiTests/OpenApiGenerationFailures/MissingFromBody/MissingFromBodyOnPatchMethodTests.cs @@ -0,0 +1,30 @@ +using FluentAssertions; +using JsonApiDotNetCore.Errors; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.OpenApiGenerationFailures.MissingFromBody; + +public sealed class MissingFromBodyOnPatchMethodTests : OpenApiTestContext, MissingFromBodyDbContext> +{ + public MissingFromBodyOnPatchMethodTests(ITestOutputHelper testOutputHelper) + { + UseController(); + + SetTestOutputHelper(testOutputHelper); + } + + [Fact] + public async Task Cannot_use_Patch_controller_action_method_without_FromBody_attribute() + { + // Act + Func action = async () => _ = await GetSwaggerDocumentAsync(); + + // Assert + string? actionMethod = typeof(MissingFromBodyOnPatchController).GetMethod(nameof(MissingFromBodyOnPatchController.AlternatePatchAsync))!.ToString(); + string containingType = typeof(MissingFromBodyOnPatchController).ToString(); + + await action.Should().ThrowExactlyAsync().WithMessage( + $"The action method '{actionMethod}' on type '{containingType}' contains no parameter with a [FromBody] attribute."); + } +} diff --git a/test/OpenApiTests/OpenApiGenerationFailures/MissingFromBody/MissingFromBodyOnPostController.cs b/test/OpenApiTests/OpenApiGenerationFailures/MissingFromBody/MissingFromBodyOnPostController.cs new file mode 100644 index 0000000000..479d95db40 --- /dev/null +++ b/test/OpenApiTests/OpenApiGenerationFailures/MissingFromBody/MissingFromBodyOnPostController.cs @@ -0,0 +1,19 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Services; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; + +namespace OpenApiTests.OpenApiGenerationFailures.MissingFromBody; + +public sealed class MissingFromBodyOnPostController( + IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, IResourceService resourceService) + : BaseJsonApiController(options, resourceGraph, loggerFactory, resourceService) +{ + // Not overriding the base method, to trigger the error that [FromBody] is missing. + [HttpPost] + public Task AlternatePostAsync(RecycleBin resource, CancellationToken cancellationToken) + { + return PostAsync(resource, cancellationToken); + } +} diff --git a/test/OpenApiTests/OpenApiGenerationFailures/MissingFromBody/MissingFromBodyOnPostMethodTests.cs b/test/OpenApiTests/OpenApiGenerationFailures/MissingFromBody/MissingFromBodyOnPostMethodTests.cs new file mode 100644 index 0000000000..a121f058f9 --- /dev/null +++ b/test/OpenApiTests/OpenApiGenerationFailures/MissingFromBody/MissingFromBodyOnPostMethodTests.cs @@ -0,0 +1,30 @@ +using FluentAssertions; +using JsonApiDotNetCore.Errors; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.OpenApiGenerationFailures.MissingFromBody; + +public sealed class MissingFromBodyOnPostMethodTests : OpenApiTestContext, MissingFromBodyDbContext> +{ + public MissingFromBodyOnPostMethodTests(ITestOutputHelper testOutputHelper) + { + UseController(); + + SetTestOutputHelper(testOutputHelper); + } + + [Fact] + public async Task Cannot_use_Post_controller_action_method_without_FromBody_attribute() + { + // Act + Func action = async () => _ = await GetSwaggerDocumentAsync(); + + // Assert + string? actionMethod = typeof(MissingFromBodyOnPostController).GetMethod(nameof(MissingFromBodyOnPostController.AlternatePostAsync))!.ToString(); + string containingType = typeof(MissingFromBodyOnPostController).ToString(); + + await action.Should().ThrowExactlyAsync().WithMessage( + $"The action method '{actionMethod}' on type '{containingType}' contains no parameter with a [FromBody] attribute."); + } +} diff --git a/test/OpenApiTests/OpenApiGenerationFailures/MissingFromBody/RecycleBin.cs b/test/OpenApiTests/OpenApiGenerationFailures/MissingFromBody/RecycleBin.cs new file mode 100644 index 0000000000..51df92e0da --- /dev/null +++ b/test/OpenApiTests/OpenApiGenerationFailures/MissingFromBody/RecycleBin.cs @@ -0,0 +1,14 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.OpenApiGenerationFailures.MissingFromBody; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.OpenApiGenerationFailures.MissingFromBody", GenerateControllerEndpoints = JsonApiEndpoints.None)] +public sealed class RecycleBin : Identifiable +{ + [Attr] + public bool IsEmpty { get; set; } +} diff --git a/test/OpenApiTests/OpenApiStartup.cs b/test/OpenApiTests/OpenApiStartup.cs new file mode 100644 index 0000000000..ba0a5256ca --- /dev/null +++ b/test/OpenApiTests/OpenApiStartup.cs @@ -0,0 +1,44 @@ +using System.Reflection; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.OpenApi.Swashbuckle; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Swashbuckle.AspNetCore.SwaggerGen; +using TestBuildingBlocks; + +namespace OpenApiTests; + +public class OpenApiStartup : TestableStartup + where TDbContext : TestableDbContext +{ + public override void ConfigureServices(IServiceCollection services) + { + base.ConfigureServices(services); + +#pragma warning disable JADNC_OA_001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + services.AddOpenApiForJsonApi(SetupSwaggerGenAction); +#pragma warning restore JADNC_OA_001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + } + + protected override void SetJsonApiOptions(JsonApiOptions options) + { + base.SetJsonApiOptions(options); + + options.UseRelativeLinks = true; + options.IncludeTotalResourceCount = true; + } + + protected virtual void SetupSwaggerGenAction(SwaggerGenOptions options) + { + string documentationPath = Path.ChangeExtension(Assembly.GetExecutingAssembly().Location, ".xml"); + options.IncludeXmlComments(documentationPath); + } + + public override void Configure(IApplicationBuilder app) + { + app.UseRouting(); + app.UseJsonApi(); + app.UseSwagger(); + app.UseEndpoints(endpoints => endpoints.MapControllers()); + } +} diff --git a/test/OpenApiTests/OpenApiTestContext.cs b/test/OpenApiTests/OpenApiTestContext.cs new file mode 100644 index 0000000000..7743ab7533 --- /dev/null +++ b/test/OpenApiTests/OpenApiTestContext.cs @@ -0,0 +1,95 @@ +using System.Reflection; +using System.Text.Json; +using JetBrains.Annotations; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using TestBuildingBlocks; +using Xunit.Abstractions; + +namespace OpenApiTests; + +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +public class OpenApiTestContext : IntegrationTestContext + where TStartup : class + where TDbContext : TestableDbContext +{ + private readonly Lazy> _lazySwaggerDocument; + private ITestOutputHelper? _testOutputHelper; + + internal string? SwaggerDocumentOutputDirectory { get; set; } + + public OpenApiTestContext() + { + _lazySwaggerDocument = new Lazy>(CreateSwaggerDocumentAsync, LazyThreadSafetyMode.ExecutionAndPublication); + } + + internal async Task GetSwaggerDocumentAsync() + { + return await _lazySwaggerDocument.Value; + } + + private async Task CreateSwaggerDocumentAsync() + { + string content = await GetAsync("/swagger/v1/swagger.json"); + + JsonElement rootElement = ParseSwaggerDocument(content); + + if (SwaggerDocumentOutputDirectory != null) + { + string absoluteOutputPath = GetSwaggerDocumentAbsoluteOutputPath(SwaggerDocumentOutputDirectory); + await WriteToDiskAsync(absoluteOutputPath, rootElement); + } + + return rootElement; + } + + internal void SetTestOutputHelper(ITestOutputHelper testOutputHelper) + { + ArgumentNullException.ThrowIfNull(testOutputHelper); + + _testOutputHelper = testOutputHelper; + ConfigureLogging(AddXUnitProvider); + } + + private void AddXUnitProvider(ILoggingBuilder loggingBuilder) + { + if (_testOutputHelper != null) + { + loggingBuilder.SetMinimumLevel(LogLevel.Trace); + loggingBuilder.Services.AddSingleton(_ => new XUnitLoggerProvider(_testOutputHelper, "JsonApiDotNetCore.OpenApi.Swashbuckle")); + } + } + + private static string GetSwaggerDocumentAbsoluteOutputPath(string relativePath) + { + string testRootDirectory = Path.Combine(Assembly.GetExecutingAssembly().Location, "../../../../../"); + string outputPath = Path.Combine(testRootDirectory, relativePath, "swagger.g.json"); + + return Path.GetFullPath(outputPath); + } + + private async Task GetAsync(string requestUrl) + { + using var request = new HttpRequestMessage(HttpMethod.Get, requestUrl); + + using HttpClient client = Factory.CreateClient(); + using HttpResponseMessage responseMessage = await client.SendAsync(request); + + return await responseMessage.Content.ReadAsStringAsync(); + } + + private static JsonElement ParseSwaggerDocument(string content) + { + using JsonDocument jsonDocument = JsonDocument.Parse(content); + return jsonDocument.RootElement.Clone(); + } + + private static async Task WriteToDiskAsync(string path, JsonElement jsonElement) + { + string directory = Path.GetDirectoryName(path)!; + Directory.CreateDirectory(directory); + + string contents = jsonElement.ToString(); + await File.WriteAllTextAsync(path, contents); + } +} diff --git a/test/OpenApiTests/OpenApiTests.csproj b/test/OpenApiTests/OpenApiTests.csproj new file mode 100644 index 0000000000..ed2a75b5f4 --- /dev/null +++ b/test/OpenApiTests/OpenApiTests.csproj @@ -0,0 +1,29 @@ + + + net9.0;net8.0 + True + false + $(NoWarn);1591 + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/OpenApiTests/QueryStrings/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/QueryStrings/GeneratedSwagger/swagger.g.json new file mode 100644 index 0000000000..4b5473246c --- /dev/null +++ b/test/OpenApiTests/QueryStrings/GeneratedSwagger/swagger.g.json @@ -0,0 +1,4997 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "OpenApiTests", + "version": "1.0" + }, + "servers": [ + { + "url": "http://localhost" + } + ], + "paths": { + "/nameValuePairs": { + "get": { + "tags": [ + "nameValuePairs" + ], + "summary": "Retrieves a collection of nameValuePairs.", + "operationId": "getNameValuePairCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found nameValuePairs, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nameValuePairCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "nameValuePairs" + ], + "summary": "Retrieves a collection of nameValuePairs without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headNameValuePairCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "nameValuePairs" + ], + "summary": "Creates a new nameValuePair.", + "operationId": "postNameValuePair", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the nameValuePair to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createNameValuePairRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The nameValuePair was successfully created, which resulted in additional changes. The newly created nameValuePair is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created nameValuePair can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryNameValuePairResponseDocument" + } + } + } + }, + "204": { + "description": "The nameValuePair was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/nameValuePairs/{id}": { + "get": { + "tags": [ + "nameValuePairs" + ], + "summary": "Retrieves an individual nameValuePair by its identifier.", + "operationId": "getNameValuePair", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the nameValuePair to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found nameValuePair.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryNameValuePairResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The nameValuePair does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "nameValuePairs" + ], + "summary": "Retrieves an individual nameValuePair by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headNameValuePair", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the nameValuePair to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The nameValuePair does not exist." + } + } + }, + "patch": { + "tags": [ + "nameValuePairs" + ], + "summary": "Updates an existing nameValuePair.", + "operationId": "patchNameValuePair", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the nameValuePair to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the nameValuePair to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateNameValuePairRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The nameValuePair was successfully updated, which resulted in additional changes. The updated nameValuePair is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryNameValuePairResponseDocument" + } + } + } + }, + "204": { + "description": "The nameValuePair was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The nameValuePair or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "nameValuePairs" + ], + "summary": "Deletes an existing nameValuePair by its identifier.", + "operationId": "deleteNameValuePair", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the nameValuePair to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "The nameValuePair was successfully deleted." + }, + "404": { + "description": "The nameValuePair does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/nameValuePairs/{id}/owner": { + "get": { + "tags": [ + "nameValuePairs" + ], + "summary": "Retrieves the related node of an individual nameValuePair's owner relationship.", + "operationId": "getNameValuePairOwner", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the nameValuePair whose related node to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found node, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/secondaryNodeResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The nameValuePair does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "nameValuePairs" + ], + "summary": "Retrieves the related node of an individual nameValuePair's owner relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headNameValuePairOwner", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the nameValuePair whose related node to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The nameValuePair does not exist." + } + } + } + }, + "/nameValuePairs/{id}/relationships/owner": { + "get": { + "tags": [ + "nameValuePairs" + ], + "summary": "Retrieves the related node identity of an individual nameValuePair's owner relationship.", + "operationId": "getNameValuePairOwnerRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the nameValuePair whose related node identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found node identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nodeIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The nameValuePair does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "nameValuePairs" + ], + "summary": "Retrieves the related node identity of an individual nameValuePair's owner relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headNameValuePairOwnerRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the nameValuePair whose related node identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The nameValuePair does not exist." + } + } + }, + "patch": { + "tags": [ + "nameValuePairs" + ], + "summary": "Assigns an existing node to the owner relationship of an individual nameValuePair.", + "operationId": "patchNameValuePairOwnerRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the nameValuePair whose owner relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identity of the node to assign to the owner relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneNodeInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The owner relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The nameValuePair or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/nodes": { + "get": { + "tags": [ + "nodes" + ], + "summary": "Retrieves a collection of nodes.", + "operationId": "getNodeCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found nodes, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nodeCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "nodes" + ], + "summary": "Retrieves a collection of nodes without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headNodeCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "nodes" + ], + "summary": "Creates a new node.", + "operationId": "postNode", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the node to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createNodeRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The node was successfully created, which resulted in additional changes. The newly created node is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created node can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryNodeResponseDocument" + } + } + } + }, + "204": { + "description": "The node was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/nodes/{id}": { + "get": { + "tags": [ + "nodes" + ], + "summary": "Retrieves an individual node by its identifier.", + "operationId": "getNode", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the node to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found node.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryNodeResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The node does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "nodes" + ], + "summary": "Retrieves an individual node by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headNode", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the node to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The node does not exist." + } + } + }, + "patch": { + "tags": [ + "nodes" + ], + "summary": "Updates an existing node.", + "operationId": "patchNode", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the node to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the node to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateNodeRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The node was successfully updated, which resulted in additional changes. The updated node is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryNodeResponseDocument" + } + } + } + }, + "204": { + "description": "The node was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The node or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "nodes" + ], + "summary": "Deletes an existing node by its identifier.", + "operationId": "deleteNode", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the node to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "The node was successfully deleted." + }, + "404": { + "description": "The node does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/nodes/{id}/children": { + "get": { + "tags": [ + "nodes" + ], + "summary": "Retrieves the related nodes of an individual node's children relationship.", + "operationId": "getNodeChildren", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the node whose related nodes to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found nodes, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nodeCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The node does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "nodes" + ], + "summary": "Retrieves the related nodes of an individual node's children relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headNodeChildren", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the node whose related nodes to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The node does not exist." + } + } + } + }, + "/nodes/{id}/relationships/children": { + "get": { + "tags": [ + "nodes" + ], + "summary": "Retrieves the related node identities of an individual node's children relationship.", + "operationId": "getNodeChildrenRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the node whose related node identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found node identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nodeIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The node does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "nodes" + ], + "summary": "Retrieves the related node identities of an individual node's children relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headNodeChildrenRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the node whose related node identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The node does not exist." + } + } + }, + "post": { + "tags": [ + "nodes" + ], + "summary": "Adds existing nodes to the children relationship of an individual node.", + "operationId": "postNodeChildrenRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the node to add nodes to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the nodes to add to the children relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyNodeInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The nodes were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The node or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "nodes" + ], + "summary": "Assigns existing nodes to the children relationship of an individual node.", + "operationId": "patchNodeChildrenRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the node whose children relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the nodes to assign to the children relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyNodeInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The children relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The node or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "nodes" + ], + "summary": "Removes existing nodes from the children relationship of an individual node.", + "operationId": "deleteNodeChildrenRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the node to remove nodes from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the nodes to remove from the children relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyNodeInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The nodes were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The node or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/nodes/{id}/parent": { + "get": { + "tags": [ + "nodes" + ], + "summary": "Retrieves the related node of an individual node's parent relationship.", + "operationId": "getNodeParent", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the node whose related node to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found node, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullableSecondaryNodeResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The node does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "nodes" + ], + "summary": "Retrieves the related node of an individual node's parent relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headNodeParent", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the node whose related node to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The node does not exist." + } + } + } + }, + "/nodes/{id}/relationships/parent": { + "get": { + "tags": [ + "nodes" + ], + "summary": "Retrieves the related node identity of an individual node's parent relationship.", + "operationId": "getNodeParentRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the node whose related node identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found node identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullableNodeIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The node does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "nodes" + ], + "summary": "Retrieves the related node identity of an individual node's parent relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headNodeParentRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the node whose related node identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The node does not exist." + } + } + }, + "patch": { + "tags": [ + "nodes" + ], + "summary": "Clears or assigns an existing node to the parent relationship of an individual node.", + "operationId": "patchNodeParentRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the node whose parent relationship to assign or clear.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identity of the node to assign to the parent relationship, or `null` to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneNodeInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The parent relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The node or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/nodes/{id}/values": { + "get": { + "tags": [ + "nodes" + ], + "summary": "Retrieves the related nameValuePairs of an individual node's values relationship.", + "operationId": "getNodeValues", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the node whose related nameValuePairs to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found nameValuePairs, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nameValuePairCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The node does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "nodes" + ], + "summary": "Retrieves the related nameValuePairs of an individual node's values relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headNodeValues", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the node whose related nameValuePairs to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The node does not exist." + } + } + } + }, + "/nodes/{id}/relationships/values": { + "get": { + "tags": [ + "nodes" + ], + "summary": "Retrieves the related nameValuePair identities of an individual node's values relationship.", + "operationId": "getNodeValuesRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the node whose related nameValuePair identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found nameValuePair identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nameValuePairIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The node does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "nodes" + ], + "summary": "Retrieves the related nameValuePair identities of an individual node's values relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headNodeValuesRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the node whose related nameValuePair identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The node does not exist." + } + } + }, + "post": { + "tags": [ + "nodes" + ], + "summary": "Adds existing nameValuePairs to the values relationship of an individual node.", + "operationId": "postNodeValuesRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the node to add nameValuePairs to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the nameValuePairs to add to the values relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyNameValuePairInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The nameValuePairs were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The node or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "nodes" + ], + "summary": "Assigns existing nameValuePairs to the values relationship of an individual node.", + "operationId": "patchNodeValuesRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the node whose values relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the nameValuePairs to assign to the values relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyNameValuePairInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The values relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The node or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "nodes" + ], + "summary": "Removes existing nameValuePairs from the values relationship of an individual node.", + "operationId": "deleteNodeValuesRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the node to remove nameValuePairs from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the nameValuePairs to remove from the values relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyNameValuePairInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The nameValuePairs were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The node or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "attributesInCreateNameValuePairRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateNodeRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "comment": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "nameValuePairs": "#/components/schemas/attributesInCreateNameValuePairRequest", + "nodes": "#/components/schemas/attributesInCreateNodeRequest" + } + }, + "x-abstract": true + }, + "attributesInNameValuePairResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInNodeResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "comment": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "nameValuePairs": "#/components/schemas/attributesInNameValuePairResponse", + "nodes": "#/components/schemas/attributesInNodeResponse" + } + }, + "x-abstract": true + }, + "attributesInUpdateNameValuePairRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateNodeRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "comment": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "nameValuePairs": "#/components/schemas/attributesInUpdateNameValuePairRequest", + "nodes": "#/components/schemas/attributesInUpdateNodeRequest" + } + }, + "x-abstract": true + }, + "createNameValuePairRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateNameValuePairRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "createNodeRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateNodeRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "dataInCreateNameValuePairRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateNameValuePairRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateNameValuePairRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateNodeRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateNodeRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateNodeRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInNameValuePairResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInNameValuePairResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInNameValuePairResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInNodeResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInNodeResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInNodeResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateNameValuePairRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateNameValuePairRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateNameValuePairRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateNodeRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateNodeRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateNodeRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "errorLinks": { + "type": "object", + "properties": { + "about": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorObject": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorLinks" + } + ], + "nullable": true + }, + "status": { + "type": "string" + }, + "code": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/errorSource" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorResponseDocument": { + "required": [ + "errors", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorTopLevelLinks" + } + ] + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/errorObject" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorSource": { + "type": "object", + "properties": { + "pointer": { + "type": "string", + "nullable": true + }, + "parameter": { + "type": "string", + "nullable": true + }, + "header": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "identifierInRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "nameValuePairs": "#/components/schemas/nameValuePairIdentifierInRequest", + "nodes": "#/components/schemas/nodeIdentifierInRequest" + } + }, + "x-abstract": true + }, + "meta": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "nameValuePairCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInNameValuePairResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nameValuePairIdentifierCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/nameValuePairIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nameValuePairIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "nameValuePairIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/nameValuePairResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nameValuePairResourceType": { + "enum": [ + "nameValuePairs" + ], + "type": "string" + }, + "nodeCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInNodeResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nodeIdentifierCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/nodeIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nodeIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "nodeIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/nodeResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nodeIdentifierResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/nodeIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nodeResourceType": { + "enum": [ + "nodes" + ], + "type": "string" + }, + "nullableNodeIdentifierResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/nodeIdentifierInResponse" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableSecondaryNodeResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInNodeResponse" + } + ], + "nullable": true + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableToOneNodeInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/nodeIdentifierInRequest" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableToOneNodeInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/nodeIdentifierInResponse" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryNameValuePairResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInNameValuePairResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryNodeResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInNodeResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "relationshipLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + } + }, + "additionalProperties": false + }, + "relationshipsInCreateNameValuePairRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "required": [ + "owner" + ], + "type": "object", + "properties": { + "owner": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneNodeInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateNodeRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "type": "object", + "properties": { + "values": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyNameValuePairInRequest" + } + ] + }, + "parent": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneNodeInRequest" + } + ] + }, + "children": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyNodeInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "nameValuePairs": "#/components/schemas/relationshipsInCreateNameValuePairRequest", + "nodes": "#/components/schemas/relationshipsInCreateNodeRequest" + } + }, + "x-abstract": true + }, + "relationshipsInNameValuePairResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "type": "object", + "properties": { + "owner": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneNodeInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInNodeResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "type": "object", + "properties": { + "values": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyNameValuePairInResponse" + } + ] + }, + "parent": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneNodeInResponse" + } + ] + }, + "children": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyNodeInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "nameValuePairs": "#/components/schemas/relationshipsInNameValuePairResponse", + "nodes": "#/components/schemas/relationshipsInNodeResponse" + } + }, + "x-abstract": true + }, + "relationshipsInUpdateNameValuePairRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "owner": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneNodeInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateNodeRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "values": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyNameValuePairInRequest" + } + ] + }, + "parent": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneNodeInRequest" + } + ] + }, + "children": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyNodeInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "nameValuePairs": "#/components/schemas/relationshipsInUpdateNameValuePairRequest", + "nodes": "#/components/schemas/relationshipsInUpdateNodeRequest" + } + }, + "x-abstract": true + }, + "resourceCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceIdentifierCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceIdentifierTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceInCreateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "nameValuePairs": "#/components/schemas/dataInCreateNameValuePairRequest", + "nodes": "#/components/schemas/dataInCreateNodeRequest" + } + }, + "x-abstract": true + }, + "resourceInResponse": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "nameValuePairs": "#/components/schemas/dataInNameValuePairResponse", + "nodes": "#/components/schemas/dataInNodeResponse" + } + }, + "x-abstract": true + }, + "resourceInUpdateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "nameValuePairs": "#/components/schemas/dataInUpdateNameValuePairRequest", + "nodes": "#/components/schemas/dataInUpdateNodeRequest" + } + }, + "x-abstract": true + }, + "resourceLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceType": { + "enum": [ + "nameValuePairs", + "nodes" + ], + "type": "string" + }, + "secondaryNodeResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInNodeResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyNameValuePairInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/nameValuePairIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyNameValuePairInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/nameValuePairIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyNodeInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/nodeIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyNodeInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/nodeIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneNodeInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/nodeIdentifierInRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneNodeInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/nodeIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateNameValuePairRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateNameValuePairRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateNodeRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateNodeRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/test/OpenApiTests/QueryStrings/IncludeTests.cs b/test/OpenApiTests/QueryStrings/IncludeTests.cs new file mode 100644 index 0000000000..78c82ad3d8 --- /dev/null +++ b/test/OpenApiTests/QueryStrings/IncludeTests.cs @@ -0,0 +1,78 @@ +using System.Text.Json; +using FluentAssertions; +using JetBrains.Annotations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Services; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.QueryStrings; + +public sealed class IncludeTests : IClassFixture, QueryStringDbContext>> +{ + private readonly OpenApiTestContext, QueryStringDbContext> _testContext; + + public IncludeTests(OpenApiTestContext, QueryStringDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + + testContext.UseController(); + + testContext.SetTestOutputHelper(testOutputHelper); + } + + [Fact] + public async Task Discriminator_is_generated_for_all_resource_types_when_subset_of_endpoints_is_exposed() + { + // Arrange + var resourceGraph = _testContext.Factory.Services.GetRequiredService(); + int count = resourceGraph.GetResourceTypes().Count; + + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas").With(schemasElement => + { + List discriminatorRefIds = []; + + schemasElement.Should().ContainPath("resourceInResponse.discriminator").With(discriminatorElement => + { + discriminatorElement.Should().HaveProperty("propertyName", "type"); + + discriminatorElement.Should().ContainPath("mapping").With(mappingElement => + { + foreach (JsonProperty jsonProperty in mappingElement.EnumerateObject()) + { + string discriminatorRefId = jsonProperty.Value.GetSchemaReferenceId(); + discriminatorRefIds.Add(discriminatorRefId); + } + }); + }); + + discriminatorRefIds.Should().HaveCount(count); + + foreach (string discriminatorRefId in discriminatorRefIds) + { + schemasElement.Should().ContainPath($"{discriminatorRefId}.allOf[0].$ref").ShouldBeSchemaReferenceId("resourceInResponse"); + } + }); + } + + [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] + private sealed class OnlyGetSingleNodeController( + IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, IResourceService resourceService) + : BaseJsonApiController(options, resourceGraph, loggerFactory, resourceService) + { + [HttpGet("{id}")] + public override Task GetAsync(long id, CancellationToken cancellationToken) + { + return base.GetAsync(id, cancellationToken); + } + } +} diff --git a/test/OpenApiTests/QueryStrings/NameValuePair.cs b/test/OpenApiTests/QueryStrings/NameValuePair.cs new file mode 100644 index 0000000000..ab7fd2f61e --- /dev/null +++ b/test/OpenApiTests/QueryStrings/NameValuePair.cs @@ -0,0 +1,19 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.QueryStrings; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.QueryStrings")] +public sealed class NameValuePair : Identifiable +{ + [Attr] + public string Name { get; set; } = null!; + + [Attr] + public string? Value { get; set; } + + [HasOne] + public Node Owner { get; set; } = null!; +} diff --git a/test/OpenApiTests/QueryStrings/Node.cs b/test/OpenApiTests/QueryStrings/Node.cs new file mode 100644 index 0000000000..e9da915295 --- /dev/null +++ b/test/OpenApiTests/QueryStrings/Node.cs @@ -0,0 +1,25 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.QueryStrings; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.QueryStrings")] +public sealed class Node : Identifiable +{ + [Attr] + public string Name { get; set; } = null!; + + [Attr] + public string? Comment { get; set; } + + [HasMany] + public IList Values { get; set; } = new List(); + + [HasOne] + public Node? Parent { get; set; } + + [HasMany] + public ISet Children { get; set; } = new HashSet(); +} diff --git a/test/OpenApiTests/QueryStrings/QueryStringDbContext.cs b/test/OpenApiTests/QueryStrings/QueryStringDbContext.cs new file mode 100644 index 0000000000..337540262d --- /dev/null +++ b/test/OpenApiTests/QueryStrings/QueryStringDbContext.cs @@ -0,0 +1,12 @@ +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; +using TestBuildingBlocks; + +namespace OpenApiTests.QueryStrings; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public sealed class QueryStringDbContext(DbContextOptions options) + : TestableDbContext(options) +{ + public DbSet Nodes => Set(); +} diff --git a/test/OpenApiTests/QueryStrings/QueryStringFakers.cs b/test/OpenApiTests/QueryStrings/QueryStringFakers.cs new file mode 100644 index 0000000000..63b415219a --- /dev/null +++ b/test/OpenApiTests/QueryStrings/QueryStringFakers.cs @@ -0,0 +1,25 @@ +using Bogus; +using JetBrains.Annotations; +using TestBuildingBlocks; + +// @formatter:wrap_chained_method_calls chop_if_long +// @formatter:wrap_before_first_method_call true + +namespace OpenApiTests.QueryStrings; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public sealed class QueryStringFakers +{ + private readonly Lazy> _lazyNodeFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(node => node.Name, faker => faker.Lorem.Word()) + .RuleFor(node => node.Comment, faker => faker.Lorem.Sentence())); + + private readonly Lazy> _lazyNameValuePairFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(node => node.Name, faker => faker.Lorem.Word()) + .RuleFor(node => node.Value, faker => faker.Lorem.Sentence())); + + public Faker Node => _lazyNodeFaker.Value; + public Faker NameValuePair => _lazyNameValuePairFaker.Value; +} diff --git a/test/OpenApiTests/QueryStrings/QueryStringTests.cs b/test/OpenApiTests/QueryStrings/QueryStringTests.cs new file mode 100644 index 0000000000..f74f773796 --- /dev/null +++ b/test/OpenApiTests/QueryStrings/QueryStringTests.cs @@ -0,0 +1,91 @@ +using System.Text.Json; +using FluentAssertions; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.QueryStrings; + +public sealed class QueryStringTests : IClassFixture, QueryStringDbContext>> +{ + private readonly OpenApiTestContext, QueryStringDbContext> _testContext; + + public QueryStringTests(OpenApiTestContext, QueryStringDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + + testContext.UseController(); + testContext.UseController(); + + testContext.SetTestOutputHelper(testOutputHelper); + testContext.SwaggerDocumentOutputDirectory = $"{GetType().Namespace!.Replace('.', '/')}/GeneratedSwagger"; + } + + [Theory] + [InlineData("/nodes.get")] + [InlineData("/nodes.head")] + [InlineData("/nodes.post")] + [InlineData("/nodes/{id}.get")] + [InlineData("/nodes/{id}.head")] + [InlineData("/nodes/{id}.patch")] + [InlineData("/nodes/{id}/parent.get")] + [InlineData("/nodes/{id}/parent.head")] + [InlineData("/nodes/{id}/relationships/parent.get")] + [InlineData("/nodes/{id}/relationships/parent.head")] + [InlineData("/nodes/{id}/children.get")] + [InlineData("/nodes/{id}/children.head")] + [InlineData("/nodes/{id}/relationships/children.get")] + [InlineData("/nodes/{id}/relationships/children.head")] + public async Task Endpoints_have_query_string_parameter(string endpointPath) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath($"paths.{endpointPath}").With(verbElement => + { + verbElement.Should().ContainPath("parameters").With(parametersElement => + { + parametersElement.EnumerateArray().Should().ContainSingle(element => element.GetProperty("in").ValueEquals("query")).Subject.With( + parameterElement => + { + parameterElement.Should().HaveProperty("name", "query"); + + parameterElement.Should().ContainPath("schema").With(schemaElement => + { + schemaElement.Should().HaveProperty("type", "object"); + + schemaElement.Should().ContainPath("additionalProperties").With(propertiesElement => + { + propertiesElement.Should().HaveProperty("type", "string"); + propertiesElement.Should().HaveProperty("nullable", true); + }); + + schemaElement.Should().HaveProperty("example", string.Empty); + }); + }); + }); + }); + } + + [Theory] + [InlineData("/nodes/{id}.delete")] + [InlineData("/nodes/{id}/relationships/parent.patch")] + [InlineData("/nodes/{id}/relationships/children.post")] + [InlineData("/nodes/{id}/relationships/children.patch")] + [InlineData("/nodes/{id}/relationships/children.delete")] + public async Task Endpoints_do_not_have_query_string_parameter(string endpointPath) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath($"paths.{endpointPath}").With(verbElement => + { + verbElement.Should().ContainPath("parameters").With(parametersElement => + { + parametersElement.EnumerateArray().Should().NotContain(element => element.GetProperty("in").ValueEquals("query")); + }); + }); + } +} diff --git a/test/OpenApiTests/ResourceFieldValidation/MsvOffStartup.cs b/test/OpenApiTests/ResourceFieldValidation/MsvOffStartup.cs new file mode 100644 index 0000000000..838803f9c4 --- /dev/null +++ b/test/OpenApiTests/ResourceFieldValidation/MsvOffStartup.cs @@ -0,0 +1,17 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Configuration; +using TestBuildingBlocks; + +namespace OpenApiTests.ResourceFieldValidation; + +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +public sealed class MsvOffStartup : OpenApiStartup + where TDbContext : TestableDbContext +{ + protected override void SetJsonApiOptions(JsonApiOptions options) + { + base.SetJsonApiOptions(options); + + options.ValidateModelState = false; + } +} diff --git a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/GeneratedSwagger/swagger.g.json new file mode 100644 index 0000000000..541a5901ba --- /dev/null +++ b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/GeneratedSwagger/swagger.g.json @@ -0,0 +1,3955 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "OpenApiTests", + "version": "1.0" + }, + "servers": [ + { + "url": "http://localhost" + } + ], + "paths": { + "/resources": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves a collection of resources.", + "operationId": "getResourceCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found resources, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/resourceCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves a collection of resources without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "resources" + ], + "summary": "Creates a new resource.", + "operationId": "postResource", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the resource to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createResourceRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The resource was successfully created, which resulted in additional changes. The newly created resource is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created resource can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryResourceResponseDocument" + } + } + } + }, + "204": { + "description": "The resource was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves an individual resource by its identifier.", + "operationId": "getResource", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found resource.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryResourceResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves an individual resource by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResource", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Updates an existing resource.", + "operationId": "patchResource", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the resource to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateResourceRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The resource was successfully updated, which resulted in additional changes. The updated resource is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryResourceResponseDocument" + } + } + } + }, + "204": { + "description": "The resource was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "resources" + ], + "summary": "Deletes an existing resource by its identifier.", + "operationId": "deleteResource", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "responses": { + "204": { + "description": "The resource was successfully deleted." + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}/requiredToMany": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empties of an individual resource's requiredToMany relationship.", + "operationId": "getResourceRequiredToMany", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empties to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empties, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/emptyCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empties of an individual resource's requiredToMany relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceRequiredToMany", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empties to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + } + }, + "/resources/{id}/relationships/requiredToMany": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identities of an individual resource's requiredToMany relationship.", + "operationId": "getResourceRequiredToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/emptyIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identities of an individual resource's requiredToMany relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceRequiredToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "post": { + "tags": [ + "resources" + ], + "summary": "Adds existing empties to the requiredToMany relationship of an individual resource.", + "operationId": "postResourceRequiredToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to add empties to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to add to the requiredToMany relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The empties were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Assigns existing empties to the requiredToMany relationship of an individual resource.", + "operationId": "patchResourceRequiredToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose requiredToMany relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to assign to the requiredToMany relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The requiredToMany relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "resources" + ], + "summary": "Removes existing empties from the requiredToMany relationship of an individual resource.", + "operationId": "deleteResourceRequiredToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to remove empties from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to remove from the requiredToMany relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The empties were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}/requiredToOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's requiredToOne relationship.", + "operationId": "getResourceRequiredToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullableSecondaryEmptyResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's requiredToOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceRequiredToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + } + }, + "/resources/{id}/relationships/requiredToOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's requiredToOne relationship.", + "operationId": "getResourceRequiredToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullableEmptyIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's requiredToOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceRequiredToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Clears or assigns an existing empty to the requiredToOne relationship of an individual resource.", + "operationId": "patchResourceRequiredToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose requiredToOne relationship to assign or clear.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identity of the empty to assign to the requiredToOne relationship, or `null` to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The requiredToOne relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}/toMany": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empties of an individual resource's toMany relationship.", + "operationId": "getResourceToMany", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empties to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empties, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/emptyCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empties of an individual resource's toMany relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceToMany", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empties to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + } + }, + "/resources/{id}/relationships/toMany": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identities of an individual resource's toMany relationship.", + "operationId": "getResourceToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/emptyIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identities of an individual resource's toMany relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "post": { + "tags": [ + "resources" + ], + "summary": "Adds existing empties to the toMany relationship of an individual resource.", + "operationId": "postResourceToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to add empties to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to add to the toMany relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The empties were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Assigns existing empties to the toMany relationship of an individual resource.", + "operationId": "patchResourceToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose toMany relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to assign to the toMany relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The toMany relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "resources" + ], + "summary": "Removes existing empties from the toMany relationship of an individual resource.", + "operationId": "deleteResourceToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to remove empties from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to remove from the toMany relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The empties were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}/toOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's toOne relationship.", + "operationId": "getResourceToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullableSecondaryEmptyResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's toOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + } + }, + "/resources/{id}/relationships/toOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's toOne relationship.", + "operationId": "getResourceToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullableEmptyIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's toOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Clears or assigns an existing empty to the toOne relationship of an individual resource.", + "operationId": "patchResourceToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose toOne relationship to assign or clear.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identity of the empty to assign to the toOne relationship, or `null` to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The toOne relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "attributesInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/attributesInCreateResourceRequest" + } + }, + "x-abstract": true + }, + "attributesInCreateResourceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "requiredNullableValueType", + "requiredReferenceType", + "requiredValueType" + ], + "type": "object", + "properties": { + "referenceType": { + "type": "string", + "nullable": true + }, + "requiredReferenceType": { + "minLength": 1, + "type": "string", + "nullable": true + }, + "valueType": { + "type": "integer", + "format": "int32" + }, + "requiredValueType": { + "type": "integer", + "format": "int32" + }, + "nullableValueType": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "requiredNullableValueType": { + "type": "integer", + "format": "int32", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInResourceResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "referenceType": { + "type": "string", + "nullable": true + }, + "requiredReferenceType": { + "minLength": 1, + "type": "string", + "nullable": true + }, + "valueType": { + "type": "integer", + "format": "int32" + }, + "requiredValueType": { + "type": "integer", + "format": "int32" + }, + "nullableValueType": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "requiredNullableValueType": { + "type": "integer", + "format": "int32", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/attributesInResourceResponse" + } + }, + "x-abstract": true + }, + "attributesInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/attributesInUpdateResourceRequest" + } + }, + "x-abstract": true + }, + "attributesInUpdateResourceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "referenceType": { + "type": "string", + "nullable": true + }, + "requiredReferenceType": { + "minLength": 1, + "type": "string", + "nullable": true + }, + "valueType": { + "type": "integer", + "format": "int32" + }, + "requiredValueType": { + "type": "integer", + "format": "int32" + }, + "nullableValueType": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "requiredNullableValueType": { + "type": "integer", + "format": "int32", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createResourceRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateResourceRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "dataInCreateResourceRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateResourceRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateResourceRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInEmptyResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInResourceResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResourceResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResourceResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateResourceRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateResourceRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateResourceRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "emptyCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInEmptyResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "emptyIdentifierCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/emptyIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "emptyIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "emptyIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "emptyResourceType": { + "enum": [ + "empties" + ], + "type": "string" + }, + "errorLinks": { + "type": "object", + "properties": { + "about": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorObject": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorLinks" + } + ], + "nullable": true + }, + "status": { + "type": "string" + }, + "code": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/errorSource" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorResponseDocument": { + "required": [ + "errors", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorTopLevelLinks" + } + ] + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/errorObject" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorSource": { + "type": "object", + "properties": { + "pointer": { + "type": "string", + "nullable": true + }, + "parameter": { + "type": "string", + "nullable": true + }, + "header": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "identifierInRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "empties": "#/components/schemas/emptyIdentifierInRequest" + } + }, + "x-abstract": true + }, + "meta": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "nullableEmptyIdentifierResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyIdentifierInResponse" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableSecondaryEmptyResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInEmptyResponse" + } + ], + "nullable": true + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableToOneEmptyInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyIdentifierInRequest" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableToOneEmptyInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyIdentifierInResponse" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryResourceResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInResourceResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "relationshipLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + } + }, + "additionalProperties": false + }, + "relationshipsInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/relationshipsInCreateResourceRequest" + } + }, + "x-abstract": true + }, + "relationshipsInCreateResourceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "required": [ + "requiredToMany", + "requiredToOne" + ], + "type": "object", + "properties": { + "toOne": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInRequest" + } + ] + }, + "requiredToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInRequest" + } + ] + }, + "toMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + }, + "requiredToMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInResourceResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "type": "object", + "properties": { + "toOne": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInResponse" + } + ] + }, + "requiredToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInResponse" + } + ] + }, + "toMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInResponse" + } + ] + }, + "requiredToMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/relationshipsInResourceResponse" + } + }, + "x-abstract": true + }, + "relationshipsInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/relationshipsInUpdateResourceRequest" + } + }, + "x-abstract": true + }, + "relationshipsInUpdateResourceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "toOne": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInRequest" + } + ] + }, + "requiredToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInRequest" + } + ] + }, + "toMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + }, + "requiredToMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "resourceCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInResourceResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "resourceCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceIdentifierCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceIdentifierTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceInCreateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "resources": "#/components/schemas/dataInCreateResourceRequest" + } + }, + "x-abstract": true + }, + "resourceInResponse": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "empties": "#/components/schemas/dataInEmptyResponse", + "resources": "#/components/schemas/dataInResourceResponse" + } + }, + "x-abstract": true + }, + "resourceInUpdateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "resources": "#/components/schemas/dataInUpdateResourceRequest" + } + }, + "x-abstract": true + }, + "resourceLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceType": { + "enum": [ + "empties", + "resources" + ], + "type": "string" + }, + "toManyEmptyInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/emptyIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyEmptyInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/emptyIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateResourceRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateResourceRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/NullabilityTests.cs b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/NullabilityTests.cs new file mode 100644 index 0000000000..aae027360a --- /dev/null +++ b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/NullabilityTests.cs @@ -0,0 +1,102 @@ +using System.Text.Json; +using FluentAssertions; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOff; + +public sealed class NullabilityTests : IClassFixture, NrtOffDbContext>> +{ + private readonly OpenApiTestContext, NrtOffDbContext> _testContext; + + public NullabilityTests(OpenApiTestContext, NrtOffDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + + testContext.UseController(); + + testContext.SetTestOutputHelper(testOutputHelper); + testContext.SwaggerDocumentOutputDirectory = $"{GetType().Namespace!.Replace('.', '/')}/GeneratedSwagger"; + } + + [Theory] + [InlineData("referenceType")] + [InlineData("requiredReferenceType")] + [InlineData("nullableValueType")] + [InlineData("requiredNullableValueType")] + public async Task Schema_property_for_attribute_is_nullable(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.attributesInResourceResponse.allOf[1].properties").With(schemaProperties => + { + schemaProperties.Should().ContainPath(jsonPropertyName).With(schemaProperty => + { + schemaProperty.Should().ContainPath("nullable").With(nullableProperty => nullableProperty.ValueKind.Should().Be(JsonValueKind.True)); + }); + }); + } + + [Theory] + [InlineData("valueType")] + [InlineData("requiredValueType")] + public async Task Schema_property_for_attribute_is_not_nullable(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.attributesInResourceResponse.allOf[1].properties").With(schemaProperties => + { + schemaProperties.Should().ContainPath(jsonPropertyName).With(schemaProperty => + { + schemaProperty.Should().NotContainPath("nullable"); + }); + }); + } + + [Theory] + [InlineData("toOne")] + [InlineData("requiredToOne")] + public async Task Schema_property_for_relationship_is_nullable(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.relationshipsInCreateResourceRequest.allOf[1].properties").With(schemaProperties => + { + schemaProperties.Should().ContainPath($"{jsonPropertyName}.allOf[0].$ref").WithSchemaReferenceId(schemaReferenceId => + { + document.Should().ContainPath($"components.schemas.{schemaReferenceId}.properties.data").With(relationshipDataSchema => + { + relationshipDataSchema.Should().ContainPath("nullable").With(nullableProperty => nullableProperty.Should().Be(true)); + }); + }); + }); + } + + [Theory] + [InlineData("toMany")] + [InlineData("requiredToMany")] + public async Task Schema_property_for_relationship_is_not_nullable(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.relationshipsInCreateResourceRequest.allOf[1].properties").With(schemaProperties => + { + schemaProperties.Should().ContainPath($"{jsonPropertyName}.allOf[0].$ref").WithSchemaReferenceId(schemaReferenceId => + { + document.Should().ContainPath($"components.schemas.{schemaReferenceId}.properties.data").With(relationshipDataSchema => + { + relationshipDataSchema.Should().NotContainPath("nullable"); + }); + }); + }); + } +} diff --git a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/RequiredTests.cs b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/RequiredTests.cs new file mode 100644 index 0000000000..ece2c6174a --- /dev/null +++ b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/RequiredTests.cs @@ -0,0 +1,112 @@ +using System.Text.Json; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOff; + +public sealed class RequiredTests : IClassFixture, NrtOffDbContext>> +{ + private readonly OpenApiTestContext, NrtOffDbContext> _testContext; + + public RequiredTests(OpenApiTestContext, NrtOffDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + + testContext.UseController(); + + testContext.SetTestOutputHelper(testOutputHelper); + } + + [Theory] + [InlineData("requiredReferenceType")] + [InlineData("requiredValueType")] + [InlineData("requiredNullableValueType")] + public async Task Schema_property_for_attribute_is_required_for_creating_resource(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.attributesInCreateResourceRequest.allOf[1]").With(attributesSchema => + { + attributesSchema.Should().ContainPath($"properties.{jsonPropertyName}"); + attributesSchema.Should().ContainPath("required").With(propertySet => propertySet.Should().ContainArrayElement(jsonPropertyName)); + }); + } + + [Theory] + [InlineData("referenceType")] + [InlineData("valueType")] + [InlineData("nullableValueType")] + public async Task Schema_property_for_attribute_is_not_required_for_creating_resource(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.attributesInCreateResourceRequest.allOf[1]").With(attributesSchema => + { + attributesSchema.Should().ContainPath($"properties.{jsonPropertyName}"); + attributesSchema.Should().ContainPath("required").With(propertySet => propertySet.Should().NotContainArrayElement(jsonPropertyName)); + }); + } + + [Theory] + [InlineData("requiredToOne")] + [InlineData("requiredToMany")] + public async Task Schema_property_for_relationship_is_required_for_creating_resource(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.relationshipsInCreateResourceRequest.allOf[1]").With(relationshipsSchema => + { + relationshipsSchema.Should().ContainPath($"properties.{jsonPropertyName}"); + relationshipsSchema.Should().ContainPath("required").With(propertySet => propertySet.Should().ContainArrayElement(jsonPropertyName)); + }); + } + + [Theory] + [InlineData("toOne")] + [InlineData("toMany")] + public async Task Schema_property_for_relationship_is_not_required_for_creating_resource(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.relationshipsInCreateResourceRequest.allOf[1]").With(relationshipsSchema => + { + relationshipsSchema.Should().ContainPath($"properties.{jsonPropertyName}"); + relationshipsSchema.Should().ContainPath("required").With(propertySet => propertySet.Should().NotContainArrayElement(jsonPropertyName)); + }); + } + + [Fact] + public async Task No_attribute_schema_properties_are_required_for_updating_resource() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.attributesInUpdateResourceRequest.allOf[1]").With(attributesSchema => + { + attributesSchema.Should().NotContainPath("required"); + }); + } + + [Fact] + public async Task No_relationship_schema_properties_are_required_for_updating_resource() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.relationshipsInUpdateResourceRequest.allOf[1]").With(relationshipsSchema => + { + relationshipsSchema.Should().NotContainPath("required"); + }); + } +} diff --git a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/GeneratedSwagger/swagger.g.json new file mode 100644 index 0000000000..cb83b19b17 --- /dev/null +++ b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/GeneratedSwagger/swagger.g.json @@ -0,0 +1,4065 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "OpenApiTests", + "version": "1.0" + }, + "servers": [ + { + "url": "http://localhost" + } + ], + "paths": { + "/resources": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves a collection of resources.", + "operationId": "getResourceCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found resources, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/resourceCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves a collection of resources without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "resources" + ], + "summary": "Creates a new resource.", + "operationId": "postResource", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the resource to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createResourceRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The resource was successfully created, which resulted in additional changes. The newly created resource is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created resource can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryResourceResponseDocument" + } + } + } + }, + "204": { + "description": "The resource was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves an individual resource by its identifier.", + "operationId": "getResource", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found resource.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryResourceResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves an individual resource by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResource", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Updates an existing resource.", + "operationId": "patchResource", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the resource to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateResourceRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The resource was successfully updated, which resulted in additional changes. The updated resource is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryResourceResponseDocument" + } + } + } + }, + "204": { + "description": "The resource was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "resources" + ], + "summary": "Deletes an existing resource by its identifier.", + "operationId": "deleteResource", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "responses": { + "204": { + "description": "The resource was successfully deleted." + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}/requiredToMany": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empties of an individual resource's requiredToMany relationship.", + "operationId": "getResourceRequiredToMany", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empties to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empties, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/emptyCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empties of an individual resource's requiredToMany relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceRequiredToMany", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empties to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + } + }, + "/resources/{id}/relationships/requiredToMany": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identities of an individual resource's requiredToMany relationship.", + "operationId": "getResourceRequiredToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/emptyIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identities of an individual resource's requiredToMany relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceRequiredToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "post": { + "tags": [ + "resources" + ], + "summary": "Adds existing empties to the requiredToMany relationship of an individual resource.", + "operationId": "postResourceRequiredToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to add empties to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to add to the requiredToMany relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The empties were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Assigns existing empties to the requiredToMany relationship of an individual resource.", + "operationId": "patchResourceRequiredToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose requiredToMany relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to assign to the requiredToMany relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The requiredToMany relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "resources" + ], + "summary": "Removes existing empties from the requiredToMany relationship of an individual resource.", + "operationId": "deleteResourceRequiredToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to remove empties from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to remove from the requiredToMany relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The empties were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}/requiredToOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's requiredToOne relationship.", + "operationId": "getResourceRequiredToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/secondaryEmptyResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's requiredToOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceRequiredToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + } + }, + "/resources/{id}/relationships/requiredToOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's requiredToOne relationship.", + "operationId": "getResourceRequiredToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/emptyIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's requiredToOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceRequiredToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Assigns an existing empty to the requiredToOne relationship of an individual resource.", + "operationId": "patchResourceRequiredToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose requiredToOne relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identity of the empty to assign to the requiredToOne relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The requiredToOne relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}/toMany": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empties of an individual resource's toMany relationship.", + "operationId": "getResourceToMany", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empties to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empties, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/emptyCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empties of an individual resource's toMany relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceToMany", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empties to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + } + }, + "/resources/{id}/relationships/toMany": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identities of an individual resource's toMany relationship.", + "operationId": "getResourceToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/emptyIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identities of an individual resource's toMany relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "post": { + "tags": [ + "resources" + ], + "summary": "Adds existing empties to the toMany relationship of an individual resource.", + "operationId": "postResourceToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to add empties to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to add to the toMany relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The empties were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Assigns existing empties to the toMany relationship of an individual resource.", + "operationId": "patchResourceToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose toMany relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to assign to the toMany relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The toMany relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "resources" + ], + "summary": "Removes existing empties from the toMany relationship of an individual resource.", + "operationId": "deleteResourceToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to remove empties from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to remove from the toMany relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The empties were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}/toOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's toOne relationship.", + "operationId": "getResourceToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullableSecondaryEmptyResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's toOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + } + }, + "/resources/{id}/relationships/toOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's toOne relationship.", + "operationId": "getResourceToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullableEmptyIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's toOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Clears or assigns an existing empty to the toOne relationship of an individual resource.", + "operationId": "patchResourceToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose toOne relationship to assign or clear.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identity of the empty to assign to the toOne relationship, or `null` to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The toOne relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "attributesInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/attributesInCreateResourceRequest" + } + }, + "x-abstract": true + }, + "attributesInCreateResourceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "requiredNullableValueType", + "requiredReferenceType" + ], + "type": "object", + "properties": { + "referenceType": { + "type": "string", + "nullable": true + }, + "requiredReferenceType": { + "minLength": 1, + "type": "string" + }, + "valueType": { + "type": "integer", + "format": "int32" + }, + "requiredValueType": { + "type": "integer", + "format": "int32" + }, + "nullableValueType": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "requiredNullableValueType": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInResourceResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "referenceType": { + "type": "string", + "nullable": true + }, + "requiredReferenceType": { + "minLength": 1, + "type": "string" + }, + "valueType": { + "type": "integer", + "format": "int32" + }, + "requiredValueType": { + "type": "integer", + "format": "int32" + }, + "nullableValueType": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "requiredNullableValueType": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/attributesInResourceResponse" + } + }, + "x-abstract": true + }, + "attributesInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/attributesInUpdateResourceRequest" + } + }, + "x-abstract": true + }, + "attributesInUpdateResourceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "referenceType": { + "type": "string", + "nullable": true + }, + "requiredReferenceType": { + "minLength": 1, + "type": "string" + }, + "valueType": { + "type": "integer", + "format": "int32" + }, + "requiredValueType": { + "type": "integer", + "format": "int32" + }, + "nullableValueType": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "requiredNullableValueType": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createResourceRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateResourceRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "dataInCreateResourceRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateResourceRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateResourceRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInEmptyResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInResourceResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResourceResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResourceResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateResourceRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateResourceRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateResourceRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "emptyCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInEmptyResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "emptyIdentifierCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/emptyIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "emptyIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "emptyIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "emptyIdentifierResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "emptyResourceType": { + "enum": [ + "empties" + ], + "type": "string" + }, + "errorLinks": { + "type": "object", + "properties": { + "about": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorObject": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorLinks" + } + ], + "nullable": true + }, + "status": { + "type": "string" + }, + "code": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/errorSource" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorResponseDocument": { + "required": [ + "errors", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorTopLevelLinks" + } + ] + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/errorObject" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorSource": { + "type": "object", + "properties": { + "pointer": { + "type": "string", + "nullable": true + }, + "parameter": { + "type": "string", + "nullable": true + }, + "header": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "identifierInRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "empties": "#/components/schemas/emptyIdentifierInRequest" + } + }, + "x-abstract": true + }, + "meta": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "nullableEmptyIdentifierResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyIdentifierInResponse" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableSecondaryEmptyResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInEmptyResponse" + } + ], + "nullable": true + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableToOneEmptyInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyIdentifierInRequest" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableToOneEmptyInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyIdentifierInResponse" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryResourceResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInResourceResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "relationshipLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + } + }, + "additionalProperties": false + }, + "relationshipsInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/relationshipsInCreateResourceRequest" + } + }, + "x-abstract": true + }, + "relationshipsInCreateResourceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "required": [ + "requiredToOne" + ], + "type": "object", + "properties": { + "toOne": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInRequest" + } + ] + }, + "requiredToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInRequest" + } + ] + }, + "toMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + }, + "requiredToMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInResourceResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "type": "object", + "properties": { + "toOne": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInResponse" + } + ] + }, + "requiredToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInResponse" + } + ] + }, + "toMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInResponse" + } + ] + }, + "requiredToMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/relationshipsInResourceResponse" + } + }, + "x-abstract": true + }, + "relationshipsInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/relationshipsInUpdateResourceRequest" + } + }, + "x-abstract": true + }, + "relationshipsInUpdateResourceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "toOne": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInRequest" + } + ] + }, + "requiredToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInRequest" + } + ] + }, + "toMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + }, + "requiredToMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "resourceCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInResourceResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "resourceCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceIdentifierCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceIdentifierTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceInCreateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "resources": "#/components/schemas/dataInCreateResourceRequest" + } + }, + "x-abstract": true + }, + "resourceInResponse": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "empties": "#/components/schemas/dataInEmptyResponse", + "resources": "#/components/schemas/dataInResourceResponse" + } + }, + "x-abstract": true + }, + "resourceInUpdateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "resources": "#/components/schemas/dataInUpdateResourceRequest" + } + }, + "x-abstract": true + }, + "resourceLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceType": { + "enum": [ + "empties", + "resources" + ], + "type": "string" + }, + "secondaryEmptyResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInEmptyResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyEmptyInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/emptyIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyEmptyInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/emptyIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneEmptyInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyIdentifierInRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneEmptyInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateResourceRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateResourceRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/NullabilityTests.cs b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/NullabilityTests.cs new file mode 100644 index 0000000000..32c9e93779 --- /dev/null +++ b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/NullabilityTests.cs @@ -0,0 +1,102 @@ +using System.Text.Json; +using FluentAssertions; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOn; + +public sealed class NullabilityTests : IClassFixture, NrtOffDbContext>> +{ + private readonly OpenApiTestContext, NrtOffDbContext> _testContext; + + public NullabilityTests(OpenApiTestContext, NrtOffDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + + testContext.UseController(); + + testContext.SetTestOutputHelper(testOutputHelper); + testContext.SwaggerDocumentOutputDirectory = $"{GetType().Namespace!.Replace('.', '/')}/GeneratedSwagger"; + } + + [Theory] + [InlineData("referenceType")] + [InlineData("nullableValueType")] + public async Task Schema_property_for_attribute_is_nullable(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.attributesInResourceResponse.allOf[1].properties").With(schemaProperties => + { + schemaProperties.Should().ContainPath(jsonPropertyName).With(schemaProperty => + { + schemaProperty.Should().ContainPath("nullable").With(nullableProperty => nullableProperty.ValueKind.Should().Be(JsonValueKind.True)); + }); + }); + } + + [Theory] + [InlineData("requiredReferenceType")] + [InlineData("valueType")] + [InlineData("requiredValueType")] + [InlineData("requiredNullableValueType")] + public async Task Schema_property_for_attribute_is_not_nullable(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.attributesInResourceResponse.allOf[1].properties").With(schemaProperties => + { + schemaProperties.Should().ContainPath(jsonPropertyName).With(schemaProperty => + { + schemaProperty.Should().NotContainPath("nullable"); + }); + }); + } + + [Theory] + [InlineData("toOne")] + public async Task Schema_property_for_relationship_is_nullable(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.relationshipsInCreateResourceRequest.allOf[1].properties").With(schemaProperties => + { + schemaProperties.Should().ContainPath($"{jsonPropertyName}.allOf[0].$ref").WithSchemaReferenceId(schemaReferenceId => + { + document.Should().ContainPath($"components.schemas.{schemaReferenceId}.properties.data").With(relationshipDataSchema => + { + relationshipDataSchema.Should().ContainPath("nullable").With(nullableProperty => nullableProperty.Should().Be(true)); + }); + }); + }); + } + + [Theory] + [InlineData("requiredToOne")] + [InlineData("toMany")] + [InlineData("requiredToMany")] + public async Task Schema_property_for_relationship_is_not_nullable(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.relationshipsInCreateResourceRequest.allOf[1].properties").With(schemaProperties => + { + schemaProperties.Should().ContainPath($"{jsonPropertyName}.allOf[0].$ref").WithSchemaReferenceId(schemaReferenceId => + { + document.Should().ContainPath($"components.schemas.{schemaReferenceId}.properties.data").With(relationshipDataSchema => + { + relationshipDataSchema.Should().NotContainPath("nullable"); + }); + }); + }); + } +} diff --git a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/RequiredTests.cs b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/RequiredTests.cs new file mode 100644 index 0000000000..46a45ac2fd --- /dev/null +++ b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/RequiredTests.cs @@ -0,0 +1,112 @@ +using System.Text.Json; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOn; + +public sealed class RequiredTests : IClassFixture, NrtOffDbContext>> +{ + private readonly OpenApiTestContext, NrtOffDbContext> _testContext; + + public RequiredTests(OpenApiTestContext, NrtOffDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + + testContext.UseController(); + + testContext.SetTestOutputHelper(testOutputHelper); + } + + [Theory] + [InlineData("requiredReferenceType")] + [InlineData("requiredNullableValueType")] + public async Task Schema_property_for_attribute_is_required_for_creating_resource(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.attributesInCreateResourceRequest.allOf[1]").With(attributesSchema => + { + attributesSchema.Should().ContainPath($"properties.{jsonPropertyName}"); + attributesSchema.Should().ContainPath("required").With(propertySet => propertySet.Should().ContainArrayElement(jsonPropertyName)); + }); + } + + [Theory] + [InlineData("referenceType")] + [InlineData("valueType")] + [InlineData("requiredValueType")] + [InlineData("nullableValueType")] + public async Task Schema_property_for_attribute_is_not_required_for_creating_resource(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.attributesInCreateResourceRequest.allOf[1]").With(attributesSchema => + { + attributesSchema.Should().ContainPath($"properties.{jsonPropertyName}"); + attributesSchema.Should().ContainPath("required").With(propertySet => propertySet.Should().NotContainArrayElement(jsonPropertyName)); + }); + } + + [Theory] + [InlineData("requiredToOne")] + public async Task Schema_property_for_relationship_is_required_for_creating_resource(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.relationshipsInCreateResourceRequest.allOf[1]").With(relationshipsSchema => + { + relationshipsSchema.Should().ContainPath($"properties.{jsonPropertyName}"); + relationshipsSchema.Should().ContainPath("required").With(propertySet => propertySet.Should().ContainArrayElement(jsonPropertyName)); + }); + } + + [Theory] + [InlineData("toOne")] + [InlineData("toMany")] + [InlineData("requiredToMany")] + public async Task Schema_property_for_relationship_is_not_required_for_creating_resource(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.relationshipsInCreateResourceRequest.allOf[1]").With(relationshipsSchema => + { + relationshipsSchema.Should().ContainPath($"properties.{jsonPropertyName}"); + relationshipsSchema.Should().ContainPath("required").With(propertySet => propertySet.Should().NotContainArrayElement(jsonPropertyName)); + }); + } + + [Fact] + public async Task No_attribute_schema_properties_are_required_for_updating_resource() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.attributesInUpdateResourceRequest.allOf[1]").With(attributesSchema => + { + attributesSchema.Should().NotContainPath("required"); + }); + } + + [Fact] + public async Task No_relationship_schema_properties_are_required_for_updating_resource() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.relationshipsInUpdateResourceRequest.allOf[1]").With(relationshipsSchema => + { + relationshipsSchema.Should().NotContainPath("required"); + }); + } +} diff --git a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/NrtOffDbContext.cs b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/NrtOffDbContext.cs new file mode 100644 index 0000000000..15d0cb0b96 --- /dev/null +++ b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/NrtOffDbContext.cs @@ -0,0 +1,40 @@ +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; +using TestBuildingBlocks; + +namespace OpenApiTests.ResourceFieldValidation.NullableReferenceTypesOff; + +// @formatter:wrap_chained_method_calls chop_always + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public sealed class NrtOffDbContext(DbContextOptions options) + : TestableDbContext(options) +{ + public DbSet Resources => Set(); + public DbSet Empties => Set(); + + protected override void OnModelCreating(ModelBuilder builder) + { + builder.Entity() + .HasOne(resource => resource.ToOne) + .WithOne() + .HasForeignKey("ToOneId"); + + builder.Entity() + .HasOne(resource => resource.RequiredToOne) + .WithOne() + .HasForeignKey("RequiredToOneId"); + + builder.Entity() + .HasMany(resource => resource.ToMany) + .WithOne() + .HasForeignKey("ToManyId"); + + builder.Entity() + .HasMany(resource => resource.RequiredToMany) + .WithOne() + .HasForeignKey("RequiredToManyId"); + + base.OnModelCreating(builder); + } +} diff --git a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/NrtOffEmpty.cs b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/NrtOffEmpty.cs new file mode 100644 index 0000000000..a64fd34af5 --- /dev/null +++ b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/NrtOffEmpty.cs @@ -0,0 +1,11 @@ +#nullable disable + +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.ResourceFieldValidation.NullableReferenceTypesOff; + +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +[Resource(PublicName = "empties", ControllerNamespace = "OpenApiTests.ResourceFieldValidation")] +public class NrtOffEmpty : Identifiable; diff --git a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/NrtOffResource.cs b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/NrtOffResource.cs new file mode 100644 index 0000000000..968d579d49 --- /dev/null +++ b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/NrtOffResource.cs @@ -0,0 +1,48 @@ +#nullable disable + +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.ResourceFieldValidation.NullableReferenceTypesOff; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(PublicName = "resources", ControllerNamespace = "OpenApiTests.ResourceFieldValidation")] +public sealed class NrtOffResource : Identifiable +{ + [Attr] + public string ReferenceType { get; set; } + + [Attr] + [Required] + public string RequiredReferenceType { get; set; } + + [Attr] + public int ValueType { get; set; } + + [Attr] + [Required] + public int RequiredValueType { get; set; } + + [Attr] + public int? NullableValueType { get; set; } + + [Attr] + [Required] + public int? RequiredNullableValueType { get; set; } + + [HasOne] + public NrtOffEmpty ToOne { get; set; } + + [Required] + [HasOne] + public NrtOffEmpty RequiredToOne { get; set; } + + [HasMany] + public ICollection ToMany { get; set; } = new HashSet(); + + [Required] + [HasMany] + public ICollection RequiredToMany { get; set; } = new HashSet(); +} diff --git a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/GeneratedSwagger/swagger.g.json new file mode 100644 index 0000000000..1b962dc499 --- /dev/null +++ b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/GeneratedSwagger/swagger.g.json @@ -0,0 +1,5010 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "OpenApiTests", + "version": "1.0" + }, + "servers": [ + { + "url": "http://localhost" + } + ], + "paths": { + "/resources": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves a collection of resources.", + "operationId": "getResourceCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found resources, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/resourceCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves a collection of resources without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "resources" + ], + "summary": "Creates a new resource.", + "operationId": "postResource", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the resource to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createResourceRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The resource was successfully created, which resulted in additional changes. The newly created resource is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created resource can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryResourceResponseDocument" + } + } + } + }, + "204": { + "description": "The resource was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves an individual resource by its identifier.", + "operationId": "getResource", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found resource.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryResourceResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves an individual resource by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResource", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Updates an existing resource.", + "operationId": "patchResource", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the resource to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateResourceRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The resource was successfully updated, which resulted in additional changes. The updated resource is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryResourceResponseDocument" + } + } + } + }, + "204": { + "description": "The resource was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "resources" + ], + "summary": "Deletes an existing resource by its identifier.", + "operationId": "deleteResource", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "responses": { + "204": { + "description": "The resource was successfully deleted." + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}/nonNullableToOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's nonNullableToOne relationship.", + "operationId": "getResourceNonNullableToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/secondaryEmptyResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's nonNullableToOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceNonNullableToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + } + }, + "/resources/{id}/relationships/nonNullableToOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's nonNullableToOne relationship.", + "operationId": "getResourceNonNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/emptyIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's nonNullableToOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceNonNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Assigns an existing empty to the nonNullableToOne relationship of an individual resource.", + "operationId": "patchResourceNonNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose nonNullableToOne relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identity of the empty to assign to the nonNullableToOne relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The nonNullableToOne relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}/nullableToOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's nullableToOne relationship.", + "operationId": "getResourceNullableToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullableSecondaryEmptyResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's nullableToOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceNullableToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + } + }, + "/resources/{id}/relationships/nullableToOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's nullableToOne relationship.", + "operationId": "getResourceNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullableEmptyIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's nullableToOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Clears or assigns an existing empty to the nullableToOne relationship of an individual resource.", + "operationId": "patchResourceNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose nullableToOne relationship to assign or clear.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identity of the empty to assign to the nullableToOne relationship, or `null` to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The nullableToOne relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}/requiredNonNullableToOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's requiredNonNullableToOne relationship.", + "operationId": "getResourceRequiredNonNullableToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/secondaryEmptyResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's requiredNonNullableToOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceRequiredNonNullableToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + } + }, + "/resources/{id}/relationships/requiredNonNullableToOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's requiredNonNullableToOne relationship.", + "operationId": "getResourceRequiredNonNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/emptyIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's requiredNonNullableToOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceRequiredNonNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Assigns an existing empty to the requiredNonNullableToOne relationship of an individual resource.", + "operationId": "patchResourceRequiredNonNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose requiredNonNullableToOne relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identity of the empty to assign to the requiredNonNullableToOne relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The requiredNonNullableToOne relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}/requiredNullableToOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's requiredNullableToOne relationship.", + "operationId": "getResourceRequiredNullableToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullableSecondaryEmptyResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's requiredNullableToOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceRequiredNullableToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + } + }, + "/resources/{id}/relationships/requiredNullableToOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's requiredNullableToOne relationship.", + "operationId": "getResourceRequiredNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullableEmptyIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's requiredNullableToOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceRequiredNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Clears or assigns an existing empty to the requiredNullableToOne relationship of an individual resource.", + "operationId": "patchResourceRequiredNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose requiredNullableToOne relationship to assign or clear.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identity of the empty to assign to the requiredNullableToOne relationship, or `null` to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The requiredNullableToOne relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}/requiredToMany": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empties of an individual resource's requiredToMany relationship.", + "operationId": "getResourceRequiredToMany", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empties to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empties, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/emptyCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empties of an individual resource's requiredToMany relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceRequiredToMany", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empties to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + } + }, + "/resources/{id}/relationships/requiredToMany": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identities of an individual resource's requiredToMany relationship.", + "operationId": "getResourceRequiredToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/emptyIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identities of an individual resource's requiredToMany relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceRequiredToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "post": { + "tags": [ + "resources" + ], + "summary": "Adds existing empties to the requiredToMany relationship of an individual resource.", + "operationId": "postResourceRequiredToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to add empties to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to add to the requiredToMany relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The empties were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Assigns existing empties to the requiredToMany relationship of an individual resource.", + "operationId": "patchResourceRequiredToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose requiredToMany relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to assign to the requiredToMany relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The requiredToMany relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "resources" + ], + "summary": "Removes existing empties from the requiredToMany relationship of an individual resource.", + "operationId": "deleteResourceRequiredToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to remove empties from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to remove from the requiredToMany relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The empties were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}/toMany": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empties of an individual resource's toMany relationship.", + "operationId": "getResourceToMany", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empties to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empties, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/emptyCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empties of an individual resource's toMany relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceToMany", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empties to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + } + }, + "/resources/{id}/relationships/toMany": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identities of an individual resource's toMany relationship.", + "operationId": "getResourceToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/emptyIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identities of an individual resource's toMany relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "post": { + "tags": [ + "resources" + ], + "summary": "Adds existing empties to the toMany relationship of an individual resource.", + "operationId": "postResourceToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to add empties to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to add to the toMany relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The empties were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Assigns existing empties to the toMany relationship of an individual resource.", + "operationId": "patchResourceToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose toMany relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to assign to the toMany relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The toMany relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "resources" + ], + "summary": "Removes existing empties from the toMany relationship of an individual resource.", + "operationId": "deleteResourceToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to remove empties from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to remove from the toMany relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The empties were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "attributesInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/attributesInCreateResourceRequest" + } + }, + "x-abstract": true + }, + "attributesInCreateResourceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "requiredNonNullableReferenceType", + "requiredNullableReferenceType", + "requiredNullableValueType", + "requiredValueType" + ], + "type": "object", + "properties": { + "nonNullableReferenceType": { + "type": "string" + }, + "requiredNonNullableReferenceType": { + "minLength": 1, + "type": "string" + }, + "nullableReferenceType": { + "type": "string", + "nullable": true + }, + "requiredNullableReferenceType": { + "minLength": 1, + "type": "string", + "nullable": true + }, + "valueType": { + "type": "integer", + "format": "int32" + }, + "requiredValueType": { + "type": "integer", + "format": "int32" + }, + "nullableValueType": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "requiredNullableValueType": { + "type": "integer", + "format": "int32", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInResourceResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "nonNullableReferenceType": { + "type": "string" + }, + "requiredNonNullableReferenceType": { + "minLength": 1, + "type": "string" + }, + "nullableReferenceType": { + "type": "string", + "nullable": true + }, + "requiredNullableReferenceType": { + "minLength": 1, + "type": "string", + "nullable": true + }, + "valueType": { + "type": "integer", + "format": "int32" + }, + "requiredValueType": { + "type": "integer", + "format": "int32" + }, + "nullableValueType": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "requiredNullableValueType": { + "type": "integer", + "format": "int32", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/attributesInResourceResponse" + } + }, + "x-abstract": true + }, + "attributesInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/attributesInUpdateResourceRequest" + } + }, + "x-abstract": true + }, + "attributesInUpdateResourceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "nonNullableReferenceType": { + "type": "string" + }, + "requiredNonNullableReferenceType": { + "minLength": 1, + "type": "string" + }, + "nullableReferenceType": { + "type": "string", + "nullable": true + }, + "requiredNullableReferenceType": { + "minLength": 1, + "type": "string", + "nullable": true + }, + "valueType": { + "type": "integer", + "format": "int32" + }, + "requiredValueType": { + "type": "integer", + "format": "int32" + }, + "nullableValueType": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "requiredNullableValueType": { + "type": "integer", + "format": "int32", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createResourceRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateResourceRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "dataInCreateResourceRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateResourceRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateResourceRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInEmptyResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInResourceResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResourceResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResourceResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateResourceRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateResourceRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateResourceRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "emptyCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInEmptyResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "emptyIdentifierCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/emptyIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "emptyIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "emptyIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "emptyIdentifierResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "emptyResourceType": { + "enum": [ + "empties" + ], + "type": "string" + }, + "errorLinks": { + "type": "object", + "properties": { + "about": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorObject": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorLinks" + } + ], + "nullable": true + }, + "status": { + "type": "string" + }, + "code": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/errorSource" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorResponseDocument": { + "required": [ + "errors", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorTopLevelLinks" + } + ] + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/errorObject" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorSource": { + "type": "object", + "properties": { + "pointer": { + "type": "string", + "nullable": true + }, + "parameter": { + "type": "string", + "nullable": true + }, + "header": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "identifierInRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "empties": "#/components/schemas/emptyIdentifierInRequest" + } + }, + "x-abstract": true + }, + "meta": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "nullableEmptyIdentifierResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyIdentifierInResponse" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableSecondaryEmptyResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInEmptyResponse" + } + ], + "nullable": true + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableToOneEmptyInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyIdentifierInRequest" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableToOneEmptyInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyIdentifierInResponse" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryResourceResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInResourceResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "relationshipLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + } + }, + "additionalProperties": false + }, + "relationshipsInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/relationshipsInCreateResourceRequest" + } + }, + "x-abstract": true + }, + "relationshipsInCreateResourceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "required": [ + "requiredNonNullableToOne", + "requiredNullableToOne", + "requiredToMany" + ], + "type": "object", + "properties": { + "nonNullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInRequest" + } + ] + }, + "requiredNonNullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInRequest" + } + ] + }, + "nullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInRequest" + } + ] + }, + "requiredNullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInRequest" + } + ] + }, + "toMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + }, + "requiredToMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInResourceResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "type": "object", + "properties": { + "nonNullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInResponse" + } + ] + }, + "requiredNonNullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInResponse" + } + ] + }, + "nullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInResponse" + } + ] + }, + "requiredNullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInResponse" + } + ] + }, + "toMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInResponse" + } + ] + }, + "requiredToMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/relationshipsInResourceResponse" + } + }, + "x-abstract": true + }, + "relationshipsInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/relationshipsInUpdateResourceRequest" + } + }, + "x-abstract": true + }, + "relationshipsInUpdateResourceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "nonNullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInRequest" + } + ] + }, + "requiredNonNullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInRequest" + } + ] + }, + "nullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInRequest" + } + ] + }, + "requiredNullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInRequest" + } + ] + }, + "toMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + }, + "requiredToMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "resourceCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInResourceResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "resourceCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceIdentifierCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceIdentifierTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceInCreateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "resources": "#/components/schemas/dataInCreateResourceRequest" + } + }, + "x-abstract": true + }, + "resourceInResponse": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "empties": "#/components/schemas/dataInEmptyResponse", + "resources": "#/components/schemas/dataInResourceResponse" + } + }, + "x-abstract": true + }, + "resourceInUpdateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "resources": "#/components/schemas/dataInUpdateResourceRequest" + } + }, + "x-abstract": true + }, + "resourceLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceType": { + "enum": [ + "empties", + "resources" + ], + "type": "string" + }, + "secondaryEmptyResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInEmptyResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyEmptyInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/emptyIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyEmptyInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/emptyIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneEmptyInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyIdentifierInRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneEmptyInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateResourceRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateResourceRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/NullabilityTests.cs b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/NullabilityTests.cs new file mode 100644 index 0000000000..084cb85fde --- /dev/null +++ b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/NullabilityTests.cs @@ -0,0 +1,106 @@ +using System.Text.Json; +using FluentAssertions; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOff; + +public sealed class NullabilityTests : IClassFixture, NrtOnDbContext>> +{ + private readonly OpenApiTestContext, NrtOnDbContext> _testContext; + + public NullabilityTests(OpenApiTestContext, NrtOnDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + + testContext.UseController(); + + testContext.SetTestOutputHelper(testOutputHelper); + testContext.SwaggerDocumentOutputDirectory = $"{GetType().Namespace!.Replace('.', '/')}/GeneratedSwagger"; + } + + [Theory] + [InlineData("nullableReferenceType")] + [InlineData("requiredNullableReferenceType")] + [InlineData("nullableValueType")] + [InlineData("requiredNullableValueType")] + public async Task Schema_property_for_attribute_is_nullable(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.attributesInResourceResponse.allOf[1].properties").With(schemaProperties => + { + schemaProperties.Should().ContainPath(jsonPropertyName).With(schemaProperty => + { + schemaProperty.Should().ContainPath("nullable").With(nullableProperty => nullableProperty.ValueKind.Should().Be(JsonValueKind.True)); + }); + }); + } + + [Theory] + [InlineData("nonNullableReferenceType")] + [InlineData("requiredNonNullableReferenceType")] + [InlineData("valueType")] + [InlineData("requiredValueType")] + public async Task Schema_property_for_attribute_is_not_nullable(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.attributesInResourceResponse.allOf[1].properties").With(schemaProperties => + { + schemaProperties.Should().ContainPath(jsonPropertyName).With(schemaProperty => + { + schemaProperty.Should().NotContainPath("nullable"); + }); + }); + } + + [Theory] + [InlineData("nullableToOne")] + [InlineData("requiredNullableToOne")] + public async Task Schema_property_for_relationship_is_nullable(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.relationshipsInCreateResourceRequest.allOf[1].properties").With(schemaProperties => + { + schemaProperties.Should().ContainPath($"{jsonPropertyName}.allOf[0].$ref").WithSchemaReferenceId(schemaReferenceId => + { + document.Should().ContainPath($"components.schemas.{schemaReferenceId}.properties.data").With(relationshipDataSchema => + { + relationshipDataSchema.Should().ContainPath("nullable").With(nullableProperty => nullableProperty.Should().Be(true)); + }); + }); + }); + } + + [Theory] + [InlineData("nonNullableToOne")] + [InlineData("requiredNonNullableToOne")] + [InlineData("toMany")] + [InlineData("requiredToMany")] + public async Task Schema_property_for_relationship_is_not_nullable(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.relationshipsInCreateResourceRequest.allOf[1].properties").With(schemaProperties => + { + schemaProperties.Should().ContainPath($"{jsonPropertyName}.allOf[0].$ref").WithSchemaReferenceId(schemaReferenceId => + { + document.Should().ContainPath($"components.schemas.{schemaReferenceId}.properties.data").With(relationshipDataSchema => + { + relationshipDataSchema.Should().NotContainPath("nullable"); + }); + }); + }); + } +} diff --git a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/RequiredTests.cs b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/RequiredTests.cs new file mode 100644 index 0000000000..64ee1c433e --- /dev/null +++ b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/RequiredTests.cs @@ -0,0 +1,116 @@ +using System.Text.Json; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOff; + +public sealed class RequiredTests : IClassFixture, NrtOnDbContext>> +{ + private readonly OpenApiTestContext, NrtOnDbContext> _testContext; + + public RequiredTests(OpenApiTestContext, NrtOnDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + + testContext.UseController(); + + testContext.SetTestOutputHelper(testOutputHelper); + } + + [Theory] + [InlineData("requiredNonNullableReferenceType")] + [InlineData("requiredNullableReferenceType")] + [InlineData("requiredValueType")] + [InlineData("requiredNullableValueType")] + public async Task Schema_property_for_attribute_is_required_for_creating_resource(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.attributesInCreateResourceRequest.allOf[1]").With(attributesSchema => + { + attributesSchema.Should().ContainPath($"properties.{jsonPropertyName}"); + attributesSchema.Should().ContainPath("required").With(propertySet => propertySet.Should().ContainArrayElement(jsonPropertyName)); + }); + } + + [Theory] + [InlineData("nonNullableReferenceType")] + [InlineData("nullableReferenceType")] + [InlineData("valueType")] + [InlineData("nullableValueType")] + public async Task Schema_property_for_attribute_is_not_required_for_creating_resource(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.attributesInCreateResourceRequest.allOf[1]").With(attributesSchema => + { + attributesSchema.Should().ContainPath($"properties.{jsonPropertyName}"); + attributesSchema.Should().ContainPath("required").With(propertySet => propertySet.Should().NotContainArrayElement(jsonPropertyName)); + }); + } + + [Theory] + [InlineData("requiredNonNullableToOne")] + [InlineData("requiredNullableToOne")] + [InlineData("requiredToMany")] + public async Task Schema_property_for_relationship_is_required_for_creating_resource(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.relationshipsInCreateResourceRequest.allOf[1]").With(relationshipsSchema => + { + relationshipsSchema.Should().ContainPath($"properties.{jsonPropertyName}"); + relationshipsSchema.Should().ContainPath("required").With(propertySet => propertySet.Should().ContainArrayElement(jsonPropertyName)); + }); + } + + [Theory] + [InlineData("nonNullableToOne")] + [InlineData("nullableToOne")] + [InlineData("toMany")] + public async Task Schema_property_for_relationship_is_not_required_for_creating_resource(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.relationshipsInCreateResourceRequest.allOf[1]").With(relationshipsSchema => + { + relationshipsSchema.Should().ContainPath($"properties.{jsonPropertyName}"); + relationshipsSchema.Should().ContainPath("required").With(propertySet => propertySet.Should().NotContainArrayElement(jsonPropertyName)); + }); + } + + [Fact] + public async Task No_attribute_schema_properties_are_required_for_updating_resource() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.attributesInUpdateResourceRequest.allOf[1]").With(attributesSchema => + { + attributesSchema.Should().NotContainPath("required"); + }); + } + + [Fact] + public async Task No_relationship_schema_properties_are_required_for_updating_resource() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.relationshipsInUpdateResourceRequest.allOf[1]").With(relationshipsSchema => + { + relationshipsSchema.Should().NotContainPath("required"); + }); + } +} diff --git a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/GeneratedSwagger/swagger.g.json new file mode 100644 index 0000000000..0717249aa5 --- /dev/null +++ b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/GeneratedSwagger/swagger.g.json @@ -0,0 +1,5004 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "OpenApiTests", + "version": "1.0" + }, + "servers": [ + { + "url": "http://localhost" + } + ], + "paths": { + "/resources": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves a collection of resources.", + "operationId": "getResourceCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found resources, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/resourceCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves a collection of resources without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "resources" + ], + "summary": "Creates a new resource.", + "operationId": "postResource", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the resource to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createResourceRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The resource was successfully created, which resulted in additional changes. The newly created resource is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created resource can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryResourceResponseDocument" + } + } + } + }, + "204": { + "description": "The resource was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves an individual resource by its identifier.", + "operationId": "getResource", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found resource.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryResourceResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves an individual resource by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResource", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Updates an existing resource.", + "operationId": "patchResource", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the resource to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateResourceRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The resource was successfully updated, which resulted in additional changes. The updated resource is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryResourceResponseDocument" + } + } + } + }, + "204": { + "description": "The resource was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "resources" + ], + "summary": "Deletes an existing resource by its identifier.", + "operationId": "deleteResource", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "responses": { + "204": { + "description": "The resource was successfully deleted." + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}/nonNullableToOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's nonNullableToOne relationship.", + "operationId": "getResourceNonNullableToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/secondaryEmptyResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's nonNullableToOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceNonNullableToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + } + }, + "/resources/{id}/relationships/nonNullableToOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's nonNullableToOne relationship.", + "operationId": "getResourceNonNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/emptyIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's nonNullableToOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceNonNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Assigns an existing empty to the nonNullableToOne relationship of an individual resource.", + "operationId": "patchResourceNonNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose nonNullableToOne relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identity of the empty to assign to the nonNullableToOne relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The nonNullableToOne relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}/nullableToOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's nullableToOne relationship.", + "operationId": "getResourceNullableToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullableSecondaryEmptyResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's nullableToOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceNullableToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + } + }, + "/resources/{id}/relationships/nullableToOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's nullableToOne relationship.", + "operationId": "getResourceNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullableEmptyIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's nullableToOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Clears or assigns an existing empty to the nullableToOne relationship of an individual resource.", + "operationId": "patchResourceNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose nullableToOne relationship to assign or clear.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identity of the empty to assign to the nullableToOne relationship, or `null` to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The nullableToOne relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}/requiredNonNullableToOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's requiredNonNullableToOne relationship.", + "operationId": "getResourceRequiredNonNullableToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/secondaryEmptyResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's requiredNonNullableToOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceRequiredNonNullableToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + } + }, + "/resources/{id}/relationships/requiredNonNullableToOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's requiredNonNullableToOne relationship.", + "operationId": "getResourceRequiredNonNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/emptyIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's requiredNonNullableToOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceRequiredNonNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Assigns an existing empty to the requiredNonNullableToOne relationship of an individual resource.", + "operationId": "patchResourceRequiredNonNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose requiredNonNullableToOne relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identity of the empty to assign to the requiredNonNullableToOne relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The requiredNonNullableToOne relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}/requiredNullableToOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's requiredNullableToOne relationship.", + "operationId": "getResourceRequiredNullableToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/secondaryEmptyResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty of an individual resource's requiredNullableToOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceRequiredNullableToOne", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + } + }, + "/resources/{id}/relationships/requiredNullableToOne": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's requiredNullableToOne relationship.", + "operationId": "getResourceRequiredNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/emptyIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identity of an individual resource's requiredNullableToOne relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceRequiredNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Assigns an existing empty to the requiredNullableToOne relationship of an individual resource.", + "operationId": "patchResourceRequiredNullableToOneRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose requiredNullableToOne relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identity of the empty to assign to the requiredNullableToOne relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The requiredNullableToOne relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}/requiredToMany": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empties of an individual resource's requiredToMany relationship.", + "operationId": "getResourceRequiredToMany", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empties to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empties, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/emptyCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empties of an individual resource's requiredToMany relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceRequiredToMany", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empties to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + } + }, + "/resources/{id}/relationships/requiredToMany": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identities of an individual resource's requiredToMany relationship.", + "operationId": "getResourceRequiredToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/emptyIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identities of an individual resource's requiredToMany relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceRequiredToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "post": { + "tags": [ + "resources" + ], + "summary": "Adds existing empties to the requiredToMany relationship of an individual resource.", + "operationId": "postResourceRequiredToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to add empties to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to add to the requiredToMany relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The empties were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Assigns existing empties to the requiredToMany relationship of an individual resource.", + "operationId": "patchResourceRequiredToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose requiredToMany relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to assign to the requiredToMany relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The requiredToMany relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "resources" + ], + "summary": "Removes existing empties from the requiredToMany relationship of an individual resource.", + "operationId": "deleteResourceRequiredToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to remove empties from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to remove from the requiredToMany relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The empties were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/resources/{id}/toMany": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empties of an individual resource's toMany relationship.", + "operationId": "getResourceToMany", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empties to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empties, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/emptyCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empties of an individual resource's toMany relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceToMany", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empties to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + } + }, + "/resources/{id}/relationships/toMany": { + "get": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identities of an individual resource's toMany relationship.", + "operationId": "getResourceToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found empty identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/emptyIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "resources" + ], + "summary": "Retrieves the related empty identities of an individual resource's toMany relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResourceToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose related empty identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The resource does not exist." + } + } + }, + "post": { + "tags": [ + "resources" + ], + "summary": "Adds existing empties to the toMany relationship of an individual resource.", + "operationId": "postResourceToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to add empties to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to add to the toMany relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The empties were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "resources" + ], + "summary": "Assigns existing empties to the toMany relationship of an individual resource.", + "operationId": "patchResourceToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource whose toMany relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to assign to the toMany relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The toMany relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "resources" + ], + "summary": "Removes existing empties from the toMany relationship of an individual resource.", + "operationId": "deleteResourceToManyRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the resource to remove empties from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int32" + } + } + ], + "requestBody": { + "description": "The identities of the empties to remove from the toMany relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The empties were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "attributesInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/attributesInCreateResourceRequest" + } + }, + "x-abstract": true + }, + "attributesInCreateResourceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "nonNullableReferenceType", + "requiredNonNullableReferenceType", + "requiredNullableReferenceType", + "requiredNullableValueType" + ], + "type": "object", + "properties": { + "nonNullableReferenceType": { + "type": "string" + }, + "requiredNonNullableReferenceType": { + "minLength": 1, + "type": "string" + }, + "nullableReferenceType": { + "type": "string", + "nullable": true + }, + "requiredNullableReferenceType": { + "minLength": 1, + "type": "string" + }, + "valueType": { + "type": "integer", + "format": "int32" + }, + "requiredValueType": { + "type": "integer", + "format": "int32" + }, + "nullableValueType": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "requiredNullableValueType": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInResourceResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "nonNullableReferenceType": { + "type": "string" + }, + "requiredNonNullableReferenceType": { + "minLength": 1, + "type": "string" + }, + "nullableReferenceType": { + "type": "string", + "nullable": true + }, + "requiredNullableReferenceType": { + "minLength": 1, + "type": "string" + }, + "valueType": { + "type": "integer", + "format": "int32" + }, + "requiredValueType": { + "type": "integer", + "format": "int32" + }, + "nullableValueType": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "requiredNullableValueType": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/attributesInResourceResponse" + } + }, + "x-abstract": true + }, + "attributesInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/attributesInUpdateResourceRequest" + } + }, + "x-abstract": true + }, + "attributesInUpdateResourceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "nonNullableReferenceType": { + "type": "string" + }, + "requiredNonNullableReferenceType": { + "minLength": 1, + "type": "string" + }, + "nullableReferenceType": { + "type": "string", + "nullable": true + }, + "requiredNullableReferenceType": { + "minLength": 1, + "type": "string" + }, + "valueType": { + "type": "integer", + "format": "int32" + }, + "requiredValueType": { + "type": "integer", + "format": "int32" + }, + "nullableValueType": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "requiredNullableValueType": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createResourceRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateResourceRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "dataInCreateResourceRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateResourceRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateResourceRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInEmptyResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInResourceResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResourceResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResourceResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateResourceRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateResourceRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateResourceRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "emptyCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInEmptyResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "emptyIdentifierCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/emptyIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "emptyIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "emptyIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int32" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "emptyIdentifierResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "emptyResourceType": { + "enum": [ + "empties" + ], + "type": "string" + }, + "errorLinks": { + "type": "object", + "properties": { + "about": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorObject": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorLinks" + } + ], + "nullable": true + }, + "status": { + "type": "string" + }, + "code": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/errorSource" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorResponseDocument": { + "required": [ + "errors", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorTopLevelLinks" + } + ] + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/errorObject" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorSource": { + "type": "object", + "properties": { + "pointer": { + "type": "string", + "nullable": true + }, + "parameter": { + "type": "string", + "nullable": true + }, + "header": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "identifierInRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "empties": "#/components/schemas/emptyIdentifierInRequest" + } + }, + "x-abstract": true + }, + "meta": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "nullableEmptyIdentifierResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyIdentifierInResponse" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableSecondaryEmptyResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInEmptyResponse" + } + ], + "nullable": true + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableToOneEmptyInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyIdentifierInRequest" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableToOneEmptyInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyIdentifierInResponse" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryResourceResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInResourceResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "relationshipLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + } + }, + "additionalProperties": false + }, + "relationshipsInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/relationshipsInCreateResourceRequest" + } + }, + "x-abstract": true + }, + "relationshipsInCreateResourceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "required": [ + "nonNullableToOne", + "requiredNonNullableToOne", + "requiredNullableToOne" + ], + "type": "object", + "properties": { + "nonNullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInRequest" + } + ] + }, + "requiredNonNullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInRequest" + } + ] + }, + "nullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInRequest" + } + ] + }, + "requiredNullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInRequest" + } + ] + }, + "toMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + }, + "requiredToMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInResourceResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "type": "object", + "properties": { + "nonNullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInResponse" + } + ] + }, + "requiredNonNullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInResponse" + } + ] + }, + "nullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInResponse" + } + ] + }, + "requiredNullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInResponse" + } + ] + }, + "toMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInResponse" + } + ] + }, + "requiredToMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/relationshipsInResourceResponse" + } + }, + "x-abstract": true + }, + "relationshipsInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "resources": "#/components/schemas/relationshipsInUpdateResourceRequest" + } + }, + "x-abstract": true + }, + "relationshipsInUpdateResourceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "nonNullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInRequest" + } + ] + }, + "requiredNonNullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInRequest" + } + ] + }, + "nullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneEmptyInRequest" + } + ] + }, + "requiredNullableToOne": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneEmptyInRequest" + } + ] + }, + "toMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + }, + "requiredToMany": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyEmptyInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "resourceCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInResourceResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "resourceCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceIdentifierCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceIdentifierTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceInCreateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "resources": "#/components/schemas/dataInCreateResourceRequest" + } + }, + "x-abstract": true + }, + "resourceInResponse": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "empties": "#/components/schemas/dataInEmptyResponse", + "resources": "#/components/schemas/dataInResourceResponse" + } + }, + "x-abstract": true + }, + "resourceInUpdateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "resources": "#/components/schemas/dataInUpdateResourceRequest" + } + }, + "x-abstract": true + }, + "resourceLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceType": { + "enum": [ + "empties", + "resources" + ], + "type": "string" + }, + "secondaryEmptyResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInEmptyResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyEmptyInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/emptyIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyEmptyInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/emptyIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneEmptyInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyIdentifierInRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneEmptyInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/emptyIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateResourceRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateResourceRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/NullabilityTests.cs b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/NullabilityTests.cs new file mode 100644 index 0000000000..8617f3cd28 --- /dev/null +++ b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/NullabilityTests.cs @@ -0,0 +1,106 @@ +using System.Text.Json; +using FluentAssertions; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOn; + +public sealed class NullabilityTests : IClassFixture, NrtOnDbContext>> +{ + private readonly OpenApiTestContext, NrtOnDbContext> _testContext; + + public NullabilityTests(OpenApiTestContext, NrtOnDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + + testContext.UseController(); + + testContext.SetTestOutputHelper(testOutputHelper); + testContext.SwaggerDocumentOutputDirectory = $"{GetType().Namespace!.Replace('.', '/')}/GeneratedSwagger"; + } + + [Theory] + [InlineData("nullableReferenceType")] + [InlineData("nullableValueType")] + public async Task Schema_property_for_attribute_is_nullable(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.attributesInResourceResponse.allOf[1].properties").With(schemaProperties => + { + schemaProperties.Should().ContainPath(jsonPropertyName).With(schemaProperty => + { + schemaProperty.Should().ContainPath("nullable").With(nullableProperty => nullableProperty.ValueKind.Should().Be(JsonValueKind.True)); + }); + }); + } + + [Theory] + [InlineData("nonNullableReferenceType")] + [InlineData("requiredNonNullableReferenceType")] + [InlineData("requiredNullableReferenceType")] + [InlineData("valueType")] + [InlineData("requiredValueType")] + [InlineData("requiredNullableValueType")] + public async Task Schema_property_for_attribute_is_not_nullable(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.attributesInResourceResponse.allOf[1].properties").With(schemaProperties => + { + schemaProperties.Should().ContainPath(jsonPropertyName).With(schemaProperty => + { + schemaProperty.Should().NotContainPath("nullable"); + }); + }); + } + + [Theory] + [InlineData("nullableToOne")] + public async Task Schema_property_for_relationship_is_nullable(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.relationshipsInCreateResourceRequest.allOf[1].properties").With(schemaProperties => + { + schemaProperties.Should().ContainPath($"{jsonPropertyName}.allOf[0].$ref").WithSchemaReferenceId(schemaReferenceId => + { + document.Should().ContainPath($"components.schemas.{schemaReferenceId}.properties.data").With(relationshipDataSchema => + { + relationshipDataSchema.Should().ContainPath("nullable").With(nullableProperty => nullableProperty.Should().Be(true)); + }); + }); + }); + } + + [Theory] + [InlineData("nonNullableToOne")] + [InlineData("requiredNonNullableToOne")] + [InlineData("requiredNullableToOne")] + [InlineData("toMany")] + [InlineData("requiredToMany")] + public async Task Schema_property_for_relationship_is_not_nullable(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.relationshipsInCreateResourceRequest.allOf[1].properties").With(schemaProperties => + { + schemaProperties.Should().ContainPath($"{jsonPropertyName}.allOf[0].$ref").WithSchemaReferenceId(schemaReferenceId => + { + document.Should().ContainPath($"components.schemas.{schemaReferenceId}.properties.data").With(relationshipDataSchema => + { + relationshipDataSchema.Should().NotContainPath("nullable"); + }); + }); + }); + } +} diff --git a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/RequiredTests.cs b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/RequiredTests.cs new file mode 100644 index 0000000000..ad70bcfdeb --- /dev/null +++ b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/RequiredTests.cs @@ -0,0 +1,116 @@ +using System.Text.Json; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOn; + +public sealed class RequiredTests : IClassFixture, NrtOnDbContext>> +{ + private readonly OpenApiTestContext, NrtOnDbContext> _testContext; + + public RequiredTests(OpenApiTestContext, NrtOnDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + + testContext.UseController(); + + testContext.SetTestOutputHelper(testOutputHelper); + } + + [Theory] + [InlineData("nonNullableReferenceType")] + [InlineData("requiredNonNullableReferenceType")] + [InlineData("requiredNullableReferenceType")] + [InlineData("requiredNullableValueType")] + public async Task Schema_property_for_attribute_is_required_for_creating_resource(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.attributesInCreateResourceRequest.allOf[1]").With(attributesSchema => + { + attributesSchema.Should().ContainPath($"properties.{jsonPropertyName}"); + attributesSchema.Should().ContainPath("required").With(propertySet => propertySet.Should().ContainArrayElement(jsonPropertyName)); + }); + } + + [Theory] + [InlineData("nullableReferenceType")] + [InlineData("valueType")] + [InlineData("requiredValueType")] + [InlineData("nullableValueType")] + public async Task Schema_property_for_attribute_is_not_required_for_creating_resource(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.attributesInCreateResourceRequest.allOf[1]").With(attributesSchema => + { + attributesSchema.Should().ContainPath($"properties.{jsonPropertyName}"); + attributesSchema.Should().ContainPath("required").With(propertySet => propertySet.Should().NotContainArrayElement(jsonPropertyName)); + }); + } + + [Theory] + [InlineData("nonNullableToOne")] + [InlineData("requiredNonNullableToOne")] + [InlineData("requiredNullableToOne")] + public async Task Schema_property_for_relationship_is_required_for_creating_resource(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.relationshipsInCreateResourceRequest.allOf[1]").With(relationshipsSchema => + { + relationshipsSchema.Should().ContainPath($"properties.{jsonPropertyName}"); + relationshipsSchema.Should().ContainPath("required").With(propertySet => propertySet.Should().ContainArrayElement(jsonPropertyName)); + }); + } + + [Theory] + [InlineData("nullableToOne")] + [InlineData("toMany")] + [InlineData("requiredToMany")] + public async Task Schema_property_for_relationship_is_not_required_for_creating_resource(string jsonPropertyName) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.relationshipsInCreateResourceRequest.allOf[1]").With(relationshipsSchema => + { + relationshipsSchema.Should().ContainPath($"properties.{jsonPropertyName}"); + relationshipsSchema.Should().ContainPath("required").With(propertySet => propertySet.Should().NotContainArrayElement(jsonPropertyName)); + }); + } + + [Fact] + public async Task No_attribute_schema_properties_are_required_for_updating_resource() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.attributesInUpdateResourceRequest.allOf[1]").With(attributesSchema => + { + attributesSchema.Should().NotContainPath("required"); + }); + } + + [Fact] + public async Task No_relationship_schema_properties_are_required_for_updating_resource() + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + document.Should().ContainPath("components.schemas.relationshipsInUpdateResourceRequest.allOf[1]").With(relationshipsSchema => + { + relationshipsSchema.Should().NotContainPath("required"); + }); + } +} diff --git a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/NrtOnDbContext.cs b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/NrtOnDbContext.cs new file mode 100644 index 0000000000..2a75814ced --- /dev/null +++ b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/NrtOnDbContext.cs @@ -0,0 +1,50 @@ +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; +using TestBuildingBlocks; + +namespace OpenApiTests.ResourceFieldValidation.NullableReferenceTypesOn; + +// @formatter:wrap_chained_method_calls chop_always + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public sealed class NrtOnDbContext(DbContextOptions options) + : TestableDbContext(options) +{ + public DbSet Resources => Set(); + public DbSet Empties => Set(); + + protected override void OnModelCreating(ModelBuilder builder) + { + builder.Entity() + .HasOne(resource => resource.NonNullableToOne) + .WithOne() + .HasForeignKey("NonNullableToOneId"); + + builder.Entity() + .HasOne(resource => resource.RequiredNonNullableToOne) + .WithOne() + .HasForeignKey("RequiredNonNullableToOneId"); + + builder.Entity() + .HasOne(resource => resource.NullableToOne) + .WithOne() + .HasForeignKey("NullableToOneId"); + + builder.Entity() + .HasOne(resource => resource.RequiredNullableToOne) + .WithOne() + .HasForeignKey("RequiredNullableToOneId"); + + builder.Entity() + .HasMany(resource => resource.ToMany) + .WithOne() + .HasForeignKey("ToManyId"); + + builder.Entity() + .HasMany(resource => resource.RequiredToMany) + .WithOne() + .HasForeignKey("RequiredToManyId"); + + base.OnModelCreating(builder); + } +} diff --git a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/NrtOnEmpty.cs b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/NrtOnEmpty.cs new file mode 100644 index 0000000000..259cfda06e --- /dev/null +++ b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/NrtOnEmpty.cs @@ -0,0 +1,9 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.ResourceFieldValidation.NullableReferenceTypesOn; + +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +[Resource(PublicName = "empties", ControllerNamespace = "OpenApiTests.ResourceFieldValidation")] +public class NrtOnEmpty : Identifiable; diff --git a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/NrtOnResource.cs b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/NrtOnResource.cs new file mode 100644 index 0000000000..efc897cea2 --- /dev/null +++ b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/NrtOnResource.cs @@ -0,0 +1,60 @@ +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.ResourceFieldValidation.NullableReferenceTypesOn; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(PublicName = "resources", ControllerNamespace = "OpenApiTests.ResourceFieldValidation")] +public sealed class NrtOnResource : Identifiable +{ + [Attr] + public string NonNullableReferenceType { get; set; } = null!; + + [Attr] + [Required] + public string RequiredNonNullableReferenceType { get; set; } = null!; + + [Attr] + public string? NullableReferenceType { get; set; } + + [Attr] + [Required] + public string? RequiredNullableReferenceType { get; set; } + + [Attr] + public int ValueType { get; set; } + + [Attr] + [Required] + public int RequiredValueType { get; set; } + + [Attr] + public int? NullableValueType { get; set; } + + [Attr] + [Required] + public int? RequiredNullableValueType { get; set; } + + [HasOne] + public NrtOnEmpty NonNullableToOne { get; set; } = null!; + + [Required] + [HasOne] + public NrtOnEmpty RequiredNonNullableToOne { get; set; } = null!; + + [HasOne] + public NrtOnEmpty? NullableToOne { get; set; } + + [Required] + [HasOne] + public NrtOnEmpty? RequiredNullableToOne { get; set; } + + [HasMany] + public ICollection ToMany { get; set; } = new HashSet(); + + [Required] + [HasMany] + public ICollection RequiredToMany { get; set; } = new HashSet(); +} diff --git a/test/OpenApiTests/ResourceInheritance/Everything/EverythingInheritanceTests.cs b/test/OpenApiTests/ResourceInheritance/Everything/EverythingInheritanceTests.cs new file mode 100644 index 0000000000..09ff3fb81a --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/Everything/EverythingInheritanceTests.cs @@ -0,0 +1,338 @@ +using JsonApiDotNetCore.Controllers; +using OpenApiTests.ResourceInheritance.Models; +using Xunit; +using Xunit.Abstractions; + +#pragma warning disable format + +namespace OpenApiTests.ResourceInheritance.Everything; + +public sealed class EverythingInheritanceTests( + OpenApiTestContext, ResourceInheritanceDbContext> testContext, ITestOutputHelper testOutputHelper) + : ResourceInheritanceTests(testContext, testOutputHelper, true, false) +{ + [Theory] + [InlineData(typeof(District), JsonApiEndpoints.All)] + [InlineData(typeof(StaffMember), JsonApiEndpoints.All)] + [InlineData(typeof(Building), JsonApiEndpoints.All)] + [InlineData(typeof(Residence), JsonApiEndpoints.All)] + [InlineData(typeof(FamilyHome), JsonApiEndpoints.All)] + [InlineData(typeof(Mansion), JsonApiEndpoints.All)] + [InlineData(typeof(Room), JsonApiEndpoints.All)] + [InlineData(typeof(Kitchen), JsonApiEndpoints.All)] + [InlineData(typeof(Bedroom), JsonApiEndpoints.All)] + [InlineData(typeof(Bathroom), JsonApiEndpoints.All)] + [InlineData(typeof(LivingRoom), JsonApiEndpoints.All)] + [InlineData(typeof(Toilet), JsonApiEndpoints.All)] + [InlineData(typeof(Road), JsonApiEndpoints.All)] + [InlineData(typeof(CyclePath), JsonApiEndpoints.All)] + public override async Task Only_expected_endpoints_are_exposed(Type resourceClrType, JsonApiEndpoints expected) + { + await base.Only_expected_endpoints_are_exposed(resourceClrType, expected); + } + + [Theory] + [InlineData(true)] + public override async Task Operations_endpoint_is_exposed(bool enabled) + { + await base.Operations_endpoint_is_exposed(enabled); + } + + [Theory] + [InlineData("resourceInCreateRequest", false, + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|districts|roads|cyclePaths|staffMembers")] + [InlineData("resourceInUpdateRequest", false, + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|districts|roads|cyclePaths|staffMembers")] + [InlineData("identifierInRequest", false, + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|districts|roads|cyclePaths|staffMembers")] + [InlineData("resourceInResponse", false, + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|districts|roads|cyclePaths|staffMembers")] + [InlineData("dataInBuildingResponse", true, "familyHomes|mansions|residences")] + [InlineData("buildingIdentifierInResponse", false, "familyHomes|mansions|residences")] + [InlineData("dataInResidenceResponse", true, "familyHomes|mansions")] + [InlineData("residenceIdentifierInResponse", true, "familyHomes|mansions")] + [InlineData("dataInRoomResponse", true, "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("roomIdentifierInResponse", false, "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("dataInRoadResponse", true, "cyclePaths")] + [InlineData("roadIdentifierInResponse", false, "cyclePaths")] + public override async Task Expected_names_appear_in_type_discriminator_mapping(string schemaName, bool isWrapped, string? discriminatorValues) + { + await base.Expected_names_appear_in_type_discriminator_mapping(schemaName, isWrapped, discriminatorValues); + } + + [Theory] + [InlineData("attributesInCreateRequest", + "familyHomes|mansions|residences|buildings|bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|cyclePaths|roads|districts|staffMembers")] + [InlineData("attributesInUpdateRequest", + "familyHomes|mansions|residences|buildings|bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|cyclePaths|roads|districts|staffMembers")] + [InlineData("relationshipsInCreateRequest", + "familyHomes|mansions|residences|buildings|bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|cyclePaths|roads|districts")] + [InlineData("relationshipsInUpdateRequest", + "familyHomes|mansions|residences|buildings|bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|cyclePaths|roads|districts")] + [InlineData("!attributesInBuildingResponse", "familyHomes|mansions|residences")] + [InlineData("!relationshipsInBuildingResponse", "familyHomes|mansions|residences")] + [InlineData("!attributesInRoomResponse", "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("!relationshipsInRoomResponse", "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("!attributesInRoadResponse", "cyclePaths")] + [InlineData("!relationshipsInRoadResponse", "cyclePaths")] + [InlineData("atomicOperation", + // @formatter:keep_existing_linebreaks true + "addBuilding|updateBuilding|removeBuilding|" + + "addResidence|updateResidence|removeResidence|addToResidenceRooms|updateResidenceRooms|removeFromResidenceRooms|" + + "addFamilyHome|updateFamilyHome|removeFamilyHome|addToFamilyHomeRooms|updateFamilyHomeRooms|removeFromFamilyHomeRooms|" + + "addMansion|updateMansion|removeMansion|addToMansionRooms|updateMansionRooms|removeFromMansionRooms|addToMansionStaff|updateMansionStaff|removeFromMansionStaff|" + + "addRoom|updateRoom|removeRoom|updateRoomResidence|" + + "addBathroom|updateBathroom|removeBathroom|updateBathroomResidence|" + + "addBedroom|updateBedroom|removeBedroom|updateBedroomResidence|" + + "addKitchen|updateKitchen|removeKitchen|updateKitchenResidence|" + + "addLivingRoom|updateLivingRoom|removeLivingRoom|updateLivingRoomResidence|" + + "addToilet|updateToilet|removeToilet|updateToiletResidence|" + + "addDistrict|updateDistrict|removeDistrict|addToDistrictBuildings|updateDistrictBuildings|removeFromDistrictBuildings|addToDistrictRoads|updateDistrictRoads|removeFromDistrictRoads|" + + "addRoad|updateRoad|removeRoad|" + + "addCyclePath|updateCyclePath|removeCyclePath|" + + "addStaffMember|updateStaffMember|removeStaffMember" + // @formatter:keep_existing_linebreaks restore + )] + public override async Task Expected_names_appear_in_openapi_discriminator_mapping(string schemaName, string? discriminatorValues) + { + await base.Expected_names_appear_in_openapi_discriminator_mapping(schemaName, discriminatorValues); + } + + [Theory] + [InlineData("buildingResourceType", "familyHomes|mansions|residences")] + [InlineData("residenceResourceType", "familyHomes|mansions|residences")] + [InlineData("familyHomeResourceType", null)] + [InlineData("mansionResourceType", "mansions")] + [InlineData("roomResourceType", "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("bathroomResourceType", null)] + [InlineData("bedroomResourceType", null)] + [InlineData("kitchenResourceType", null)] + [InlineData("livingRoomResourceType", null)] + [InlineData("toiletResourceType", null)] + [InlineData("roadResourceType", "roads|cyclePaths")] + [InlineData("cyclePathResourceType", null)] + [InlineData("districtResourceType", "districts")] + [InlineData("staffMemberResourceType", "staffMembers")] + [InlineData("resourceType", + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|roads|cyclePaths|districts|staffMembers")] + public override async Task Expected_names_appear_in_resource_type_enum(string schemaName, string? enumValues) + { + await base.Expected_names_appear_in_resource_type_enum(schemaName, enumValues); + } + + [Theory] + [InlineData("resourceInCreateRequest", true, null, "type|meta")] + [InlineData("attributesInCreateRequest", true, null, "openapi:discriminator")] + [InlineData("relationshipsInCreateRequest", true, null, "openapi:discriminator")] + [InlineData("resourceInUpdateRequest", true, null, "type|meta")] + [InlineData("attributesInUpdateRequest", true, null, "openapi:discriminator")] + [InlineData("relationshipsInUpdateRequest", true, null, "openapi:discriminator")] + [InlineData("identifierInRequest", true, null, "type|meta")] + [InlineData("resourceInResponse", true, null, "type|meta")] + [InlineData("atomicOperation", true, null, "openapi:discriminator|meta")] + // Building hierarchy: Resource Data + [InlineData("dataInCreateBuildingRequest", true, "resourceInCreateRequest", "lid|attributes|relationships")] + [InlineData("dataInCreateResidenceRequest", false, "dataInCreateBuildingRequest", null)] + [InlineData("dataInCreateFamilyHomeRequest", false, "dataInCreateResidenceRequest", null)] + [InlineData("dataInCreateMansionRequest", false, "dataInCreateResidenceRequest", null)] + [InlineData("dataInUpdateBuildingRequest", true, "resourceInUpdateRequest", "id|lid|attributes|relationships")] + [InlineData("dataInUpdateResidenceRequest", false, "dataInUpdateBuildingRequest", null)] + [InlineData("dataInUpdateFamilyHomeRequest", false, "dataInUpdateResidenceRequest", null)] + [InlineData("dataInUpdateMansionRequest", false, "dataInUpdateResidenceRequest", null)] + [InlineData("dataInBuildingResponse", true, "resourceInResponse", "id|attributes|relationships|links")] + [InlineData("dataInResidenceResponse", false, "dataInBuildingResponse", null)] + [InlineData("dataInFamilyHomeResponse", false, "dataInResidenceResponse", null)] + [InlineData("dataInMansionResponse", false, "dataInResidenceResponse", null)] + // Building hierarchy: Attributes + [InlineData("attributesInCreateBuildingRequest", true, "attributesInCreateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInCreateResidenceRequest", false, "attributesInCreateBuildingRequest", "numberOfResidents")] + [InlineData("attributesInCreateFamilyHomeRequest", false, "attributesInCreateResidenceRequest", "floorCount")] + [InlineData("attributesInCreateMansionRequest", false, "attributesInCreateResidenceRequest", "ownerName")] + [InlineData("attributesInUpdateBuildingRequest", true, "attributesInUpdateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInUpdateResidenceRequest", false, "attributesInUpdateBuildingRequest", "numberOfResidents")] + [InlineData("attributesInUpdateFamilyHomeRequest", false, "attributesInUpdateResidenceRequest", "floorCount")] + [InlineData("attributesInUpdateMansionRequest", false, "attributesInUpdateResidenceRequest", "ownerName")] + [InlineData("attributesInBuildingResponse", true, "attributesInResponse", "surfaceInSquareMeters")] + [InlineData("attributesInResidenceResponse", false, "attributesInBuildingResponse", "numberOfResidents")] + [InlineData("attributesInFamilyHomeResponse", false, "attributesInResidenceResponse", "floorCount")] + [InlineData("attributesInMansionResponse", false, "attributesInResidenceResponse", "ownerName")] + // Building hierarchy: Relationships + [InlineData("relationshipsInCreateBuildingRequest", true, "relationshipsInCreateRequest", null)] + [InlineData("relationshipsInCreateResidenceRequest", false, "relationshipsInCreateBuildingRequest", "rooms")] + [InlineData("relationshipsInCreateFamilyHomeRequest", false, "relationshipsInCreateResidenceRequest", null)] + [InlineData("relationshipsInCreateMansionRequest", false, "relationshipsInCreateResidenceRequest", "staff")] + [InlineData("relationshipsInUpdateBuildingRequest", true, "relationshipsInUpdateRequest", null)] + [InlineData("relationshipsInUpdateResidenceRequest", false, "relationshipsInUpdateBuildingRequest", "rooms")] + [InlineData("relationshipsInUpdateFamilyHomeRequest", false, "relationshipsInUpdateResidenceRequest", null)] + [InlineData("relationshipsInUpdateMansionRequest", false, "relationshipsInUpdateResidenceRequest", "staff")] + [InlineData("relationshipsInBuildingResponse", true, "relationshipsInResponse", null)] + [InlineData("relationshipsInResidenceResponse", false, "relationshipsInBuildingResponse", "rooms")] + [InlineData("relationshipsInFamilyHomeResponse", false, "relationshipsInResidenceResponse", null)] + [InlineData("relationshipsInMansionResponse", false, "relationshipsInResidenceResponse", "staff")] + // Building hierarchy: Resource Identifiers + [InlineData("buildingIdentifierInRequest", false, "identifierInRequest", "id|lid")] + [InlineData("residenceIdentifierInRequest", false, "buildingIdentifierInRequest", null)] + [InlineData("familyHomeIdentifierInRequest", false, "residenceIdentifierInRequest", null)] + [InlineData("mansionIdentifierInRequest", false, "residenceIdentifierInRequest", null)] + [InlineData("buildingIdentifierInResponse", true, null, "type|id|meta")] + [InlineData("residenceIdentifierInResponse", false, "buildingIdentifierInResponse", null)] + [InlineData("familyHomeIdentifierInResponse", false, "residenceIdentifierInResponse", null)] + [InlineData("mansionIdentifierInResponse", false, "residenceIdentifierInResponse", null)] + // Building hierarchy: Atomic Operations + [InlineData("createBuildingOperation", false, "atomicOperation", "op|data")] + [InlineData("createResidenceOperation", false, "createBuildingOperation", null)] + [InlineData("createFamilyHomeOperation", false, "createResidenceOperation", null)] + [InlineData("createMansionOperation", false, "createResidenceOperation", null)] + [InlineData("updateBuildingOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateResidenceOperation", false, "updateBuildingOperation", null)] + [InlineData("updateFamilyHomeOperation", false, "updateResidenceOperation", null)] + [InlineData("updateMansionOperation", false, "updateResidenceOperation", null)] + [InlineData("deleteBuildingOperation", false, "atomicOperation", "op|ref")] + [InlineData("deleteResidenceOperation", false, "deleteBuildingOperation", null)] + [InlineData("deleteFamilyHomeOperation", false, "deleteResidenceOperation", null)] + [InlineData("deleteMansionOperation", false, "deleteResidenceOperation", null)] + [InlineData("updateResidenceRoomsRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateFamilyHomeRoomsRelationshipOperation", false, "updateResidenceRoomsRelationshipOperation", null)] + [InlineData("updateMansionRoomsRelationshipOperation", false, "updateResidenceRoomsRelationshipOperation", null)] + [InlineData("updateMansionStaffRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("addToResidenceRoomsRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("addToFamilyHomeRoomsRelationshipOperation", false, "addToResidenceRoomsRelationshipOperation", null)] + [InlineData("addToMansionRoomsRelationshipOperation", false, "addToResidenceRoomsRelationshipOperation", null)] + [InlineData("addToMansionStaffRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("removeFromResidenceRoomsRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("removeFromFamilyHomeRoomsRelationshipOperation", false, "removeFromResidenceRoomsRelationshipOperation", null)] + [InlineData("removeFromMansionRoomsRelationshipOperation", false, "removeFromResidenceRoomsRelationshipOperation", null)] + [InlineData("removeFromMansionStaffRelationshipOperation", false, "atomicOperation", "op|ref|data")] + // Room hierarchy: Resource Data + [InlineData("dataInCreateRoomRequest", true, "resourceInCreateRequest", "lid|attributes|relationships")] + [InlineData("dataInCreateBathroomRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateBedroomRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateKitchenRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateLivingRoomRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateToiletRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInUpdateRoomRequest", true, "resourceInUpdateRequest", "id|lid|attributes|relationships")] + [InlineData("dataInUpdateBathroomRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInUpdateBedroomRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInUpdateKitchenRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInUpdateLivingRoomRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInUpdateToiletRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInRoomResponse", true, "resourceInResponse", "id|attributes|relationships|links")] + [InlineData("dataInBathroomResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInBedroomResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInKitchenResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInLivingRoomResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInToiletResponse", false, "dataInRoomResponse", null)] + // Room hierarchy: Attributes + [InlineData("attributesInCreateRoomRequest", true, "attributesInCreateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInCreateBathroomRequest", false, "attributesInCreateRoomRequest", "hasBath")] + [InlineData("attributesInCreateBedroomRequest", false, "attributesInCreateRoomRequest", "bedCount")] + [InlineData("attributesInCreateKitchenRequest", false, "attributesInCreateRoomRequest", "hasPantry")] + [InlineData("attributesInCreateLivingRoomRequest", false, "attributesInCreateRoomRequest", "hasDiningTable")] + [InlineData("attributesInCreateToiletRequest", false, "attributesInCreateRoomRequest", "hasSink")] + [InlineData("attributesInUpdateRoomRequest", true, "attributesInUpdateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInUpdateBathroomRequest", false, "attributesInUpdateRoomRequest", "hasBath")] + [InlineData("attributesInUpdateBedroomRequest", false, "attributesInUpdateRoomRequest", "bedCount")] + [InlineData("attributesInUpdateKitchenRequest", false, "attributesInUpdateRoomRequest", "hasPantry")] + [InlineData("attributesInUpdateLivingRoomRequest", false, "attributesInUpdateRoomRequest", "hasDiningTable")] + [InlineData("attributesInUpdateToiletRequest", false, "attributesInUpdateRoomRequest", "hasSink")] + [InlineData("attributesInRoomResponse", true, "attributesInResponse", "surfaceInSquareMeters")] + [InlineData("attributesInBathroomResponse", false, "attributesInRoomResponse", "hasBath")] + [InlineData("attributesInBedroomResponse", false, "attributesInRoomResponse", "bedCount")] + [InlineData("attributesInKitchenResponse", false, "attributesInRoomResponse", "hasPantry")] + [InlineData("attributesInLivingRoomResponse", false, "attributesInRoomResponse", "hasDiningTable")] + [InlineData("attributesInToiletResponse", false, "attributesInRoomResponse", "hasSink")] + // Room hierarchy: Relationships + [InlineData("relationshipsInCreateRoomRequest", true, "relationshipsInCreateRequest", "residence")] + [InlineData("relationshipsInCreateBathroomRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateBedroomRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateKitchenRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateLivingRoomRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateToiletRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInUpdateRoomRequest", true, "relationshipsInUpdateRequest", "residence")] + [InlineData("relationshipsInUpdateBathroomRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInUpdateBedroomRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInUpdateKitchenRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInUpdateLivingRoomRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInUpdateToiletRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInRoomResponse", true, "relationshipsInResponse", "residence")] + [InlineData("relationshipsInBathroomResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInBedroomResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInKitchenResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInLivingRoomResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInToiletResponse", false, "relationshipsInRoomResponse", null)] + // Room hierarchy: Resource Identifiers + [InlineData("roomIdentifierInRequest", false, "identifierInRequest", "id|lid")] + [InlineData("bathroomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("bedroomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("kitchenIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("livingRoomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("toiletIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("roomIdentifierInResponse", true, null, "type|id|meta")] + [InlineData("bathroomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("bedroomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("kitchenIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("livingRoomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("toiletIdentifierInResponse", false, "roomIdentifierInResponse", null)] + // Room hierarchy: Atomic Operations + [InlineData("createRoomOperation", false, "atomicOperation", "op|data")] + [InlineData("createBathroomOperation", false, "createRoomOperation", null)] + [InlineData("createBedroomOperation", false, "createRoomOperation", null)] + [InlineData("createKitchenOperation", false, "createRoomOperation", null)] + [InlineData("createLivingRoomOperation", false, "createRoomOperation", null)] + [InlineData("createToiletOperation", false, "createRoomOperation", null)] + [InlineData("updateRoomOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateBathroomOperation", false, "updateRoomOperation", null)] + [InlineData("updateBedroomOperation", false, "updateRoomOperation", null)] + [InlineData("updateKitchenOperation", false, "updateRoomOperation", null)] + [InlineData("updateLivingRoomOperation", false, "updateRoomOperation", null)] + [InlineData("updateToiletOperation", false, "updateRoomOperation", null)] + [InlineData("deleteRoomOperation", false, "atomicOperation", "op|ref")] + [InlineData("deleteBathroomOperation", false, "deleteRoomOperation", null)] + [InlineData("deleteBedroomOperation", false, "deleteRoomOperation", null)] + [InlineData("deleteKitchenOperation", false, "deleteRoomOperation", null)] + [InlineData("deleteLivingRoomOperation", false, "deleteRoomOperation", null)] + [InlineData("deleteToiletOperation", false, "deleteRoomOperation", null)] + [InlineData("updateRoomResidenceRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateBathroomResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + [InlineData("updateBedroomResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + [InlineData("updateKitchenResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + [InlineData("updateLivingRoomResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + [InlineData("updateToiletResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + // Road hierarchy: Resource Data + [InlineData("dataInCreateRoadRequest", false, "resourceInCreateRequest", "lid|attributes|relationships")] + [InlineData("dataInCreateCyclePathRequest", false, "dataInCreateRoadRequest", null)] + [InlineData("dataInUpdateRoadRequest", false, "resourceInUpdateRequest", "id|lid|attributes|relationships")] + [InlineData("dataInUpdateCyclePathRequest", false, "dataInUpdateRoadRequest", null)] + [InlineData("dataInRoadResponse", false, "resourceInResponse", "id|attributes|relationships|links")] + [InlineData("dataInCyclePathResponse", false, "dataInRoadResponse", null)] + // Road hierarchy: Attributes + [InlineData("attributesInCreateRoadRequest", false, "attributesInCreateRequest", "lengthInMeters")] + [InlineData("attributesInCreateCyclePathRequest", false, "attributesInCreateRoadRequest", "hasLaneForPedestrians")] + [InlineData("attributesInUpdateRoadRequest", false, "attributesInUpdateRequest", "lengthInMeters")] + [InlineData("attributesInUpdateCyclePathRequest", false, "attributesInUpdateRoadRequest", "hasLaneForPedestrians")] + [InlineData("attributesInRoadResponse", false, "attributesInResponse", "lengthInMeters")] + [InlineData("attributesInCyclePathResponse", false, "attributesInRoadResponse", "hasLaneForPedestrians")] + // Road hierarchy: Relationships + [InlineData("relationshipsInCreateRoadRequest", false, "relationshipsInCreateRequest", null)] + [InlineData("relationshipsInCreateCyclePathRequest", false, "relationshipsInCreateRoadRequest", null)] + [InlineData("relationshipsInUpdateRoadRequest", false, "relationshipsInUpdateRequest", null)] + [InlineData("relationshipsInUpdateCyclePathRequest", false, "relationshipsInUpdateRoadRequest", null)] + [InlineData("relationshipsInRoadResponse", false, "relationshipsInResponse", null)] + [InlineData("relationshipsInCyclePathResponse", false, "relationshipsInRoadResponse", null)] + // Road hierarchy: Resource Identifiers + [InlineData("roadIdentifierInRequest", false, "identifierInRequest", "id|lid")] + [InlineData("cyclePathIdentifierInRequest", false, "roadIdentifierInRequest", null)] + [InlineData("roadIdentifierInResponse", false, null, "type|id|meta")] + [InlineData("cyclePathIdentifierInResponse", false, "roadIdentifierInResponse", null)] + // Road hierarchy: Atomic Operations + [InlineData("createRoadOperation", false, "atomicOperation", "op|data")] + [InlineData("createCyclePathOperation", false, "createRoadOperation", null)] + [InlineData("updateRoadOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateCyclePathOperation", false, "updateRoadOperation", null)] + [InlineData("deleteRoadOperation", false, "atomicOperation", "op|ref")] + [InlineData("deleteCyclePathOperation", false, "deleteRoadOperation", null)] + public override async Task Component_schemas_have_expected_base_type(string schemaName, bool isAbstract, string? baseType, string? properties) + { + await base.Component_schemas_have_expected_base_type(schemaName, isAbstract, baseType, properties); + } +} diff --git a/test/OpenApiTests/ResourceInheritance/Models/Bathroom.cs b/test/OpenApiTests/ResourceInheritance/Models/Bathroom.cs new file mode 100644 index 0000000000..1b67bd24b1 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/Models/Bathroom.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.ResourceInheritance.Models; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.ResourceInheritance")] +public sealed class Bathroom : Room +{ + [Attr] + [Required] + public bool? HasBath { get; set; } +} diff --git a/test/OpenApiTests/ResourceInheritance/Models/Bedroom.cs b/test/OpenApiTests/ResourceInheritance/Models/Bedroom.cs new file mode 100644 index 0000000000..3cf0a22e11 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/Models/Bedroom.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.ResourceInheritance.Models; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.ResourceInheritance")] +public sealed class Bedroom : Room +{ + [Attr] + [Required] + public int? BedCount { get; set; } +} diff --git a/test/OpenApiTests/ResourceInheritance/Models/Building.cs b/test/OpenApiTests/ResourceInheritance/Models/Building.cs new file mode 100644 index 0000000000..361a3a374f --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/Models/Building.cs @@ -0,0 +1,15 @@ +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.ResourceInheritance.Models; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.ResourceInheritance")] +public abstract class Building : Identifiable +{ + [Attr] + [Required] + public int? SurfaceInSquareMeters { get; set; } +} diff --git a/test/OpenApiTests/ResourceInheritance/Models/CyclePath.cs b/test/OpenApiTests/ResourceInheritance/Models/CyclePath.cs new file mode 100644 index 0000000000..e282e47306 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/Models/CyclePath.cs @@ -0,0 +1,12 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.ResourceInheritance.Models; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.ResourceInheritance")] +public sealed class CyclePath : Road +{ + [Attr] + public bool HasLaneForPedestrians { get; set; } +} diff --git a/test/OpenApiTests/ResourceInheritance/Models/District.cs b/test/OpenApiTests/ResourceInheritance/Models/District.cs new file mode 100644 index 0000000000..3ef752e386 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/Models/District.cs @@ -0,0 +1,19 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.ResourceInheritance.Models; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.ResourceInheritance")] +public sealed class District : Identifiable +{ + [Attr] + public string Name { get; set; } = null!; + + [HasMany] + public ISet Buildings { get; set; } = new HashSet(); + + [HasMany] + public ISet Roads { get; set; } = new HashSet(); +} diff --git a/test/OpenApiTests/ResourceInheritance/Models/FamilyHome.cs b/test/OpenApiTests/ResourceInheritance/Models/FamilyHome.cs new file mode 100644 index 0000000000..37533383c3 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/Models/FamilyHome.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.ResourceInheritance.Models; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.ResourceInheritance")] +public sealed class FamilyHome : Residence +{ + [Attr] + [Required] + public int FloorCount { get; set; } +} diff --git a/test/OpenApiTests/ResourceInheritance/Models/Kitchen.cs b/test/OpenApiTests/ResourceInheritance/Models/Kitchen.cs new file mode 100644 index 0000000000..d20206fe7e --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/Models/Kitchen.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.ResourceInheritance.Models; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.ResourceInheritance")] +public sealed class Kitchen : Room +{ + [Attr] + [Required] + public bool? HasPantry { get; set; } +} diff --git a/test/OpenApiTests/ResourceInheritance/Models/LivingRoom.cs b/test/OpenApiTests/ResourceInheritance/Models/LivingRoom.cs new file mode 100644 index 0000000000..467f5f5aa3 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/Models/LivingRoom.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.ResourceInheritance.Models; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.ResourceInheritance")] +public sealed class LivingRoom : Room +{ + [Attr] + [Required] + public bool? HasDiningTable { get; set; } +} diff --git a/test/OpenApiTests/ResourceInheritance/Models/Mansion.cs b/test/OpenApiTests/ResourceInheritance/Models/Mansion.cs new file mode 100644 index 0000000000..acf87c8eee --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/Models/Mansion.cs @@ -0,0 +1,15 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.ResourceInheritance.Models; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.ResourceInheritance")] +public sealed class Mansion : Residence +{ + [Attr] + public string OwnerName { get; set; } = null!; + + [HasMany] + public ISet Staff { get; set; } = new HashSet(); +} diff --git a/test/OpenApiTests/ResourceInheritance/Models/Residence.cs b/test/OpenApiTests/ResourceInheritance/Models/Residence.cs new file mode 100644 index 0000000000..fa6ca835cf --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/Models/Residence.cs @@ -0,0 +1,17 @@ +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.ResourceInheritance.Models; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.ResourceInheritance")] +public class Residence : Building +{ + [Attr] + [Required] + public int? NumberOfResidents { get; set; } + + [HasMany] + public ISet Rooms { get; set; } = new HashSet(); +} diff --git a/test/OpenApiTests/ResourceInheritance/Models/Road.cs b/test/OpenApiTests/ResourceInheritance/Models/Road.cs new file mode 100644 index 0000000000..c89d7a5d4b --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/Models/Road.cs @@ -0,0 +1,13 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.ResourceInheritance.Models; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.ResourceInheritance")] +public class Road : Identifiable +{ + [Attr] + public decimal LengthInMeters { get; set; } +} diff --git a/test/OpenApiTests/ResourceInheritance/Models/Room.cs b/test/OpenApiTests/ResourceInheritance/Models/Room.cs new file mode 100644 index 0000000000..6cf38598b7 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/Models/Room.cs @@ -0,0 +1,18 @@ +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.ResourceInheritance.Models; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.ResourceInheritance")] +public abstract class Room : Identifiable +{ + [Attr] + [Required] + public int? SurfaceInSquareMeters { get; set; } + + [HasOne] + public Residence Residence { get; set; } = null!; +} diff --git a/test/OpenApiTests/ResourceInheritance/Models/StaffMember.cs b/test/OpenApiTests/ResourceInheritance/Models/StaffMember.cs new file mode 100644 index 0000000000..0baa95db7e --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/Models/StaffMember.cs @@ -0,0 +1,13 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.ResourceInheritance.Models; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.ResourceInheritance")] +public sealed class StaffMember : Identifiable +{ + [Attr] + public string Name { get; set; } = null!; +} diff --git a/test/OpenApiTests/ResourceInheritance/Models/Toilet.cs b/test/OpenApiTests/ResourceInheritance/Models/Toilet.cs new file mode 100644 index 0000000000..9cade078ec --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/Models/Toilet.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.ResourceInheritance.Models; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.ResourceInheritance")] +public sealed class Toilet : Room +{ + [Attr] + [Required] + public bool? HasSink { get; set; } +} diff --git a/test/OpenApiTests/ResourceInheritance/NoOperations/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/ResourceInheritance/NoOperations/GeneratedSwagger/swagger.g.json new file mode 100644 index 0000000000..9dad8a07cb --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/NoOperations/GeneratedSwagger/swagger.g.json @@ -0,0 +1,20013 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "OpenApiTests", + "version": "1.0" + }, + "servers": [ + { + "url": "http://localhost" + } + ], + "paths": { + "/bathrooms": { + "get": { + "tags": [ + "bathrooms" + ], + "summary": "Retrieves a collection of bathrooms.", + "operationId": "getBathroomCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found bathrooms, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/bathroomCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "bathrooms" + ], + "summary": "Retrieves a collection of bathrooms without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headBathroomCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "bathrooms" + ], + "summary": "Creates a new bathroom.", + "operationId": "postBathroom", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the bathroom to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createBathroomRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The bathroom was successfully created, which resulted in additional changes. The newly created bathroom is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created bathroom can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryBathroomResponseDocument" + } + } + } + }, + "204": { + "description": "The bathroom was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/bathrooms/{id}": { + "get": { + "tags": [ + "bathrooms" + ], + "summary": "Retrieves an individual bathroom by its identifier.", + "operationId": "getBathroom", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bathroom to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found bathroom.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryBathroomResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The bathroom does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "bathrooms" + ], + "summary": "Retrieves an individual bathroom by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headBathroom", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bathroom to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The bathroom does not exist." + } + } + }, + "patch": { + "tags": [ + "bathrooms" + ], + "summary": "Updates an existing bathroom.", + "operationId": "patchBathroom", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bathroom to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the bathroom to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateBathroomRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The bathroom was successfully updated, which resulted in additional changes. The updated bathroom is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryBathroomResponseDocument" + } + } + } + }, + "204": { + "description": "The bathroom was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The bathroom or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "bathrooms" + ], + "summary": "Deletes an existing bathroom by its identifier.", + "operationId": "deleteBathroom", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bathroom to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "The bathroom was successfully deleted." + }, + "404": { + "description": "The bathroom does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/bathrooms/{id}/residence": { + "get": { + "tags": [ + "bathrooms" + ], + "summary": "Retrieves the related residence of an individual bathroom's residence relationship.", + "operationId": "getBathroomResidence", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bathroom whose related residence to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found residence, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/secondaryResidenceResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The bathroom does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "bathrooms" + ], + "summary": "Retrieves the related residence of an individual bathroom's residence relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headBathroomResidence", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bathroom whose related residence to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The bathroom does not exist." + } + } + } + }, + "/bathrooms/{id}/relationships/residence": { + "get": { + "tags": [ + "bathrooms" + ], + "summary": "Retrieves the related residence identity of an individual bathroom's residence relationship.", + "operationId": "getBathroomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bathroom whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found residence identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/residenceIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The bathroom does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "bathrooms" + ], + "summary": "Retrieves the related residence identity of an individual bathroom's residence relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headBathroomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bathroom whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The bathroom does not exist." + } + } + }, + "patch": { + "tags": [ + "bathrooms" + ], + "summary": "Assigns an existing residence to the residence relationship of an individual bathroom.", + "operationId": "patchBathroomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bathroom whose residence relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identity of the residence to assign to the residence relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneResidenceInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The residence relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The bathroom or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/bedrooms": { + "get": { + "tags": [ + "bedrooms" + ], + "summary": "Retrieves a collection of bedrooms.", + "operationId": "getBedroomCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found bedrooms, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/bedroomCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "bedrooms" + ], + "summary": "Retrieves a collection of bedrooms without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headBedroomCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "bedrooms" + ], + "summary": "Creates a new bedroom.", + "operationId": "postBedroom", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the bedroom to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createBedroomRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The bedroom was successfully created, which resulted in additional changes. The newly created bedroom is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created bedroom can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryBedroomResponseDocument" + } + } + } + }, + "204": { + "description": "The bedroom was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/bedrooms/{id}": { + "get": { + "tags": [ + "bedrooms" + ], + "summary": "Retrieves an individual bedroom by its identifier.", + "operationId": "getBedroom", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bedroom to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found bedroom.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryBedroomResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The bedroom does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "bedrooms" + ], + "summary": "Retrieves an individual bedroom by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headBedroom", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bedroom to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The bedroom does not exist." + } + } + }, + "patch": { + "tags": [ + "bedrooms" + ], + "summary": "Updates an existing bedroom.", + "operationId": "patchBedroom", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bedroom to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the bedroom to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateBedroomRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The bedroom was successfully updated, which resulted in additional changes. The updated bedroom is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryBedroomResponseDocument" + } + } + } + }, + "204": { + "description": "The bedroom was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The bedroom or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "bedrooms" + ], + "summary": "Deletes an existing bedroom by its identifier.", + "operationId": "deleteBedroom", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bedroom to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "The bedroom was successfully deleted." + }, + "404": { + "description": "The bedroom does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/bedrooms/{id}/residence": { + "get": { + "tags": [ + "bedrooms" + ], + "summary": "Retrieves the related residence of an individual bedroom's residence relationship.", + "operationId": "getBedroomResidence", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bedroom whose related residence to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found residence, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/secondaryResidenceResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The bedroom does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "bedrooms" + ], + "summary": "Retrieves the related residence of an individual bedroom's residence relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headBedroomResidence", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bedroom whose related residence to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The bedroom does not exist." + } + } + } + }, + "/bedrooms/{id}/relationships/residence": { + "get": { + "tags": [ + "bedrooms" + ], + "summary": "Retrieves the related residence identity of an individual bedroom's residence relationship.", + "operationId": "getBedroomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bedroom whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found residence identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/residenceIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The bedroom does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "bedrooms" + ], + "summary": "Retrieves the related residence identity of an individual bedroom's residence relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headBedroomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bedroom whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The bedroom does not exist." + } + } + }, + "patch": { + "tags": [ + "bedrooms" + ], + "summary": "Assigns an existing residence to the residence relationship of an individual bedroom.", + "operationId": "patchBedroomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bedroom whose residence relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identity of the residence to assign to the residence relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneResidenceInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The residence relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The bedroom or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/buildings": { + "get": { + "tags": [ + "buildings" + ], + "summary": "Retrieves a collection of buildings.", + "operationId": "getBuildingCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found buildings, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/buildingCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "buildings" + ], + "summary": "Retrieves a collection of buildings without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headBuildingCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "buildings" + ], + "summary": "Creates a new building.", + "operationId": "postBuilding", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the building to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createBuildingRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The building was successfully created, which resulted in additional changes. The newly created building is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created building can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryBuildingResponseDocument" + } + } + } + }, + "204": { + "description": "The building was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/buildings/{id}": { + "get": { + "tags": [ + "buildings" + ], + "summary": "Retrieves an individual building by its identifier.", + "operationId": "getBuilding", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the building to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found building.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryBuildingResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The building does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "buildings" + ], + "summary": "Retrieves an individual building by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headBuilding", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the building to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The building does not exist." + } + } + }, + "patch": { + "tags": [ + "buildings" + ], + "summary": "Updates an existing building.", + "operationId": "patchBuilding", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the building to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the building to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateBuildingRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The building was successfully updated, which resulted in additional changes. The updated building is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryBuildingResponseDocument" + } + } + } + }, + "204": { + "description": "The building was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The building or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "buildings" + ], + "summary": "Deletes an existing building by its identifier.", + "operationId": "deleteBuilding", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the building to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "The building was successfully deleted." + }, + "404": { + "description": "The building does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/cyclePaths": { + "get": { + "tags": [ + "cyclePaths" + ], + "summary": "Retrieves a collection of cyclePaths.", + "operationId": "getCyclePathCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found cyclePaths, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/cyclePathCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "cyclePaths" + ], + "summary": "Retrieves a collection of cyclePaths without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headCyclePathCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "cyclePaths" + ], + "summary": "Creates a new cyclePath.", + "operationId": "postCyclePath", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the cyclePath to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createCyclePathRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The cyclePath was successfully created, which resulted in additional changes. The newly created cyclePath is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created cyclePath can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryCyclePathResponseDocument" + } + } + } + }, + "204": { + "description": "The cyclePath was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/cyclePaths/{id}": { + "get": { + "tags": [ + "cyclePaths" + ], + "summary": "Retrieves an individual cyclePath by its identifier.", + "operationId": "getCyclePath", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the cyclePath to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found cyclePath.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryCyclePathResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The cyclePath does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "cyclePaths" + ], + "summary": "Retrieves an individual cyclePath by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headCyclePath", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the cyclePath to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The cyclePath does not exist." + } + } + }, + "patch": { + "tags": [ + "cyclePaths" + ], + "summary": "Updates an existing cyclePath.", + "operationId": "patchCyclePath", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the cyclePath to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the cyclePath to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateCyclePathRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The cyclePath was successfully updated, which resulted in additional changes. The updated cyclePath is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryCyclePathResponseDocument" + } + } + } + }, + "204": { + "description": "The cyclePath was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The cyclePath or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "cyclePaths" + ], + "summary": "Deletes an existing cyclePath by its identifier.", + "operationId": "deleteCyclePath", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the cyclePath to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "The cyclePath was successfully deleted." + }, + "404": { + "description": "The cyclePath does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/districts": { + "get": { + "tags": [ + "districts" + ], + "summary": "Retrieves a collection of districts.", + "operationId": "getDistrictCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found districts, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/districtCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "districts" + ], + "summary": "Retrieves a collection of districts without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headDistrictCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "districts" + ], + "summary": "Creates a new district.", + "operationId": "postDistrict", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the district to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createDistrictRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The district was successfully created, which resulted in additional changes. The newly created district is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created district can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryDistrictResponseDocument" + } + } + } + }, + "204": { + "description": "The district was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/districts/{id}": { + "get": { + "tags": [ + "districts" + ], + "summary": "Retrieves an individual district by its identifier.", + "operationId": "getDistrict", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found district.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryDistrictResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The district does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "districts" + ], + "summary": "Retrieves an individual district by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headDistrict", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The district does not exist." + } + } + }, + "patch": { + "tags": [ + "districts" + ], + "summary": "Updates an existing district.", + "operationId": "patchDistrict", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the district to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateDistrictRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The district was successfully updated, which resulted in additional changes. The updated district is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryDistrictResponseDocument" + } + } + } + }, + "204": { + "description": "The district was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The district or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "districts" + ], + "summary": "Deletes an existing district by its identifier.", + "operationId": "deleteDistrict", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "204": { + "description": "The district was successfully deleted." + }, + "404": { + "description": "The district does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/districts/{id}/buildings": { + "get": { + "tags": [ + "districts" + ], + "summary": "Retrieves the related buildings of an individual district's buildings relationship.", + "operationId": "getDistrictBuildings", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district whose related buildings to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found buildings, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/buildingCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The district does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "districts" + ], + "summary": "Retrieves the related buildings of an individual district's buildings relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headDistrictBuildings", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district whose related buildings to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The district does not exist." + } + } + } + }, + "/districts/{id}/relationships/buildings": { + "get": { + "tags": [ + "districts" + ], + "summary": "Retrieves the related building identities of an individual district's buildings relationship.", + "operationId": "getDistrictBuildingsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district whose related building identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found building identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/buildingIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The district does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "districts" + ], + "summary": "Retrieves the related building identities of an individual district's buildings relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headDistrictBuildingsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district whose related building identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The district does not exist." + } + } + }, + "post": { + "tags": [ + "districts" + ], + "summary": "Adds existing buildings to the buildings relationship of an individual district.", + "operationId": "postDistrictBuildingsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district to add buildings to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "description": "The identities of the buildings to add to the buildings relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyBuildingInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The buildings were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The district or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "districts" + ], + "summary": "Assigns existing buildings to the buildings relationship of an individual district.", + "operationId": "patchDistrictBuildingsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district whose buildings relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "description": "The identities of the buildings to assign to the buildings relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyBuildingInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The buildings relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The district or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "districts" + ], + "summary": "Removes existing buildings from the buildings relationship of an individual district.", + "operationId": "deleteDistrictBuildingsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district to remove buildings from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "description": "The identities of the buildings to remove from the buildings relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyBuildingInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The buildings were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The district or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/districts/{id}/roads": { + "get": { + "tags": [ + "districts" + ], + "summary": "Retrieves the related roads of an individual district's roads relationship.", + "operationId": "getDistrictRoads", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district whose related roads to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found roads, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/roadCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The district does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "districts" + ], + "summary": "Retrieves the related roads of an individual district's roads relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headDistrictRoads", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district whose related roads to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The district does not exist." + } + } + } + }, + "/districts/{id}/relationships/roads": { + "get": { + "tags": [ + "districts" + ], + "summary": "Retrieves the related road identities of an individual district's roads relationship.", + "operationId": "getDistrictRoadsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district whose related road identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found road identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/roadIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The district does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "districts" + ], + "summary": "Retrieves the related road identities of an individual district's roads relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headDistrictRoadsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district whose related road identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The district does not exist." + } + } + }, + "post": { + "tags": [ + "districts" + ], + "summary": "Adds existing roads to the roads relationship of an individual district.", + "operationId": "postDistrictRoadsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district to add roads to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "description": "The identities of the roads to add to the roads relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoadInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The roads were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The district or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "districts" + ], + "summary": "Assigns existing roads to the roads relationship of an individual district.", + "operationId": "patchDistrictRoadsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district whose roads relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "description": "The identities of the roads to assign to the roads relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoadInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The roads relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The district or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "districts" + ], + "summary": "Removes existing roads from the roads relationship of an individual district.", + "operationId": "deleteDistrictRoadsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district to remove roads from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "description": "The identities of the roads to remove from the roads relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoadInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The roads were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The district or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/familyHomes": { + "get": { + "tags": [ + "familyHomes" + ], + "summary": "Retrieves a collection of familyHomes.", + "operationId": "getFamilyHomeCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found familyHomes, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/familyHomeCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "familyHomes" + ], + "summary": "Retrieves a collection of familyHomes without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headFamilyHomeCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "familyHomes" + ], + "summary": "Creates a new familyHome.", + "operationId": "postFamilyHome", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the familyHome to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createFamilyHomeRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The familyHome was successfully created, which resulted in additional changes. The newly created familyHome is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created familyHome can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryFamilyHomeResponseDocument" + } + } + } + }, + "204": { + "description": "The familyHome was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/familyHomes/{id}": { + "get": { + "tags": [ + "familyHomes" + ], + "summary": "Retrieves an individual familyHome by its identifier.", + "operationId": "getFamilyHome", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the familyHome to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found familyHome.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryFamilyHomeResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The familyHome does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "familyHomes" + ], + "summary": "Retrieves an individual familyHome by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headFamilyHome", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the familyHome to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The familyHome does not exist." + } + } + }, + "patch": { + "tags": [ + "familyHomes" + ], + "summary": "Updates an existing familyHome.", + "operationId": "patchFamilyHome", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the familyHome to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the familyHome to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateFamilyHomeRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The familyHome was successfully updated, which resulted in additional changes. The updated familyHome is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryFamilyHomeResponseDocument" + } + } + } + }, + "204": { + "description": "The familyHome was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The familyHome or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "familyHomes" + ], + "summary": "Deletes an existing familyHome by its identifier.", + "operationId": "deleteFamilyHome", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the familyHome to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "The familyHome was successfully deleted." + }, + "404": { + "description": "The familyHome does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/familyHomes/{id}/rooms": { + "get": { + "tags": [ + "familyHomes" + ], + "summary": "Retrieves the related rooms of an individual familyHome's rooms relationship.", + "operationId": "getFamilyHomeRooms", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the familyHome whose related rooms to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found rooms, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/roomCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The familyHome does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "familyHomes" + ], + "summary": "Retrieves the related rooms of an individual familyHome's rooms relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headFamilyHomeRooms", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the familyHome whose related rooms to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The familyHome does not exist." + } + } + } + }, + "/familyHomes/{id}/relationships/rooms": { + "get": { + "tags": [ + "familyHomes" + ], + "summary": "Retrieves the related room identities of an individual familyHome's rooms relationship.", + "operationId": "getFamilyHomeRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the familyHome whose related room identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found room identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/roomIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The familyHome does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "familyHomes" + ], + "summary": "Retrieves the related room identities of an individual familyHome's rooms relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headFamilyHomeRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the familyHome whose related room identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The familyHome does not exist." + } + } + }, + "post": { + "tags": [ + "familyHomes" + ], + "summary": "Adds existing rooms to the rooms relationship of an individual familyHome.", + "operationId": "postFamilyHomeRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the familyHome to add rooms to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the rooms to add to the rooms relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The rooms were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The familyHome or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "familyHomes" + ], + "summary": "Assigns existing rooms to the rooms relationship of an individual familyHome.", + "operationId": "patchFamilyHomeRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the familyHome whose rooms relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the rooms to assign to the rooms relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The rooms relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The familyHome or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "familyHomes" + ], + "summary": "Removes existing rooms from the rooms relationship of an individual familyHome.", + "operationId": "deleteFamilyHomeRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the familyHome to remove rooms from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the rooms to remove from the rooms relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The rooms were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The familyHome or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/kitchens": { + "get": { + "tags": [ + "kitchens" + ], + "summary": "Retrieves a collection of kitchens.", + "operationId": "getKitchenCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found kitchens, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/kitchenCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "kitchens" + ], + "summary": "Retrieves a collection of kitchens without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headKitchenCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "kitchens" + ], + "summary": "Creates a new kitchen.", + "operationId": "postKitchen", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the kitchen to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createKitchenRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The kitchen was successfully created, which resulted in additional changes. The newly created kitchen is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created kitchen can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryKitchenResponseDocument" + } + } + } + }, + "204": { + "description": "The kitchen was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/kitchens/{id}": { + "get": { + "tags": [ + "kitchens" + ], + "summary": "Retrieves an individual kitchen by its identifier.", + "operationId": "getKitchen", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the kitchen to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found kitchen.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryKitchenResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The kitchen does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "kitchens" + ], + "summary": "Retrieves an individual kitchen by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headKitchen", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the kitchen to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The kitchen does not exist." + } + } + }, + "patch": { + "tags": [ + "kitchens" + ], + "summary": "Updates an existing kitchen.", + "operationId": "patchKitchen", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the kitchen to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the kitchen to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateKitchenRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The kitchen was successfully updated, which resulted in additional changes. The updated kitchen is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryKitchenResponseDocument" + } + } + } + }, + "204": { + "description": "The kitchen was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The kitchen or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "kitchens" + ], + "summary": "Deletes an existing kitchen by its identifier.", + "operationId": "deleteKitchen", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the kitchen to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "The kitchen was successfully deleted." + }, + "404": { + "description": "The kitchen does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/kitchens/{id}/residence": { + "get": { + "tags": [ + "kitchens" + ], + "summary": "Retrieves the related residence of an individual kitchen's residence relationship.", + "operationId": "getKitchenResidence", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the kitchen whose related residence to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found residence, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/secondaryResidenceResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The kitchen does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "kitchens" + ], + "summary": "Retrieves the related residence of an individual kitchen's residence relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headKitchenResidence", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the kitchen whose related residence to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The kitchen does not exist." + } + } + } + }, + "/kitchens/{id}/relationships/residence": { + "get": { + "tags": [ + "kitchens" + ], + "summary": "Retrieves the related residence identity of an individual kitchen's residence relationship.", + "operationId": "getKitchenResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the kitchen whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found residence identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/residenceIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The kitchen does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "kitchens" + ], + "summary": "Retrieves the related residence identity of an individual kitchen's residence relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headKitchenResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the kitchen whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The kitchen does not exist." + } + } + }, + "patch": { + "tags": [ + "kitchens" + ], + "summary": "Assigns an existing residence to the residence relationship of an individual kitchen.", + "operationId": "patchKitchenResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the kitchen whose residence relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identity of the residence to assign to the residence relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneResidenceInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The residence relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The kitchen or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/livingRooms": { + "get": { + "tags": [ + "livingRooms" + ], + "summary": "Retrieves a collection of livingRooms.", + "operationId": "getLivingRoomCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found livingRooms, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/livingRoomCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "livingRooms" + ], + "summary": "Retrieves a collection of livingRooms without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headLivingRoomCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "livingRooms" + ], + "summary": "Creates a new livingRoom.", + "operationId": "postLivingRoom", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the livingRoom to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createLivingRoomRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The livingRoom was successfully created, which resulted in additional changes. The newly created livingRoom is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created livingRoom can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryLivingRoomResponseDocument" + } + } + } + }, + "204": { + "description": "The livingRoom was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/livingRooms/{id}": { + "get": { + "tags": [ + "livingRooms" + ], + "summary": "Retrieves an individual livingRoom by its identifier.", + "operationId": "getLivingRoom", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the livingRoom to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found livingRoom.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryLivingRoomResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The livingRoom does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "livingRooms" + ], + "summary": "Retrieves an individual livingRoom by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headLivingRoom", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the livingRoom to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The livingRoom does not exist." + } + } + }, + "patch": { + "tags": [ + "livingRooms" + ], + "summary": "Updates an existing livingRoom.", + "operationId": "patchLivingRoom", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the livingRoom to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the livingRoom to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateLivingRoomRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The livingRoom was successfully updated, which resulted in additional changes. The updated livingRoom is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryLivingRoomResponseDocument" + } + } + } + }, + "204": { + "description": "The livingRoom was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The livingRoom or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "livingRooms" + ], + "summary": "Deletes an existing livingRoom by its identifier.", + "operationId": "deleteLivingRoom", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the livingRoom to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "The livingRoom was successfully deleted." + }, + "404": { + "description": "The livingRoom does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/livingRooms/{id}/residence": { + "get": { + "tags": [ + "livingRooms" + ], + "summary": "Retrieves the related residence of an individual livingRoom's residence relationship.", + "operationId": "getLivingRoomResidence", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the livingRoom whose related residence to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found residence, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/secondaryResidenceResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The livingRoom does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "livingRooms" + ], + "summary": "Retrieves the related residence of an individual livingRoom's residence relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headLivingRoomResidence", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the livingRoom whose related residence to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The livingRoom does not exist." + } + } + } + }, + "/livingRooms/{id}/relationships/residence": { + "get": { + "tags": [ + "livingRooms" + ], + "summary": "Retrieves the related residence identity of an individual livingRoom's residence relationship.", + "operationId": "getLivingRoomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the livingRoom whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found residence identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/residenceIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The livingRoom does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "livingRooms" + ], + "summary": "Retrieves the related residence identity of an individual livingRoom's residence relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headLivingRoomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the livingRoom whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The livingRoom does not exist." + } + } + }, + "patch": { + "tags": [ + "livingRooms" + ], + "summary": "Assigns an existing residence to the residence relationship of an individual livingRoom.", + "operationId": "patchLivingRoomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the livingRoom whose residence relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identity of the residence to assign to the residence relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneResidenceInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The residence relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The livingRoom or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/mansions": { + "get": { + "tags": [ + "mansions" + ], + "summary": "Retrieves a collection of mansions.", + "operationId": "getMansionCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found mansions, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/mansionCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "mansions" + ], + "summary": "Retrieves a collection of mansions without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headMansionCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "mansions" + ], + "summary": "Creates a new mansion.", + "operationId": "postMansion", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the mansion to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createMansionRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The mansion was successfully created, which resulted in additional changes. The newly created mansion is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created mansion can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryMansionResponseDocument" + } + } + } + }, + "204": { + "description": "The mansion was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/mansions/{id}": { + "get": { + "tags": [ + "mansions" + ], + "summary": "Retrieves an individual mansion by its identifier.", + "operationId": "getMansion", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found mansion.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryMansionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The mansion does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "mansions" + ], + "summary": "Retrieves an individual mansion by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headMansion", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The mansion does not exist." + } + } + }, + "patch": { + "tags": [ + "mansions" + ], + "summary": "Updates an existing mansion.", + "operationId": "patchMansion", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the mansion to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateMansionRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The mansion was successfully updated, which resulted in additional changes. The updated mansion is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryMansionResponseDocument" + } + } + } + }, + "204": { + "description": "The mansion was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The mansion or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "mansions" + ], + "summary": "Deletes an existing mansion by its identifier.", + "operationId": "deleteMansion", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "The mansion was successfully deleted." + }, + "404": { + "description": "The mansion does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/mansions/{id}/rooms": { + "get": { + "tags": [ + "mansions" + ], + "summary": "Retrieves the related rooms of an individual mansion's rooms relationship.", + "operationId": "getMansionRooms", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion whose related rooms to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found rooms, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/roomCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The mansion does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "mansions" + ], + "summary": "Retrieves the related rooms of an individual mansion's rooms relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headMansionRooms", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion whose related rooms to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The mansion does not exist." + } + } + } + }, + "/mansions/{id}/relationships/rooms": { + "get": { + "tags": [ + "mansions" + ], + "summary": "Retrieves the related room identities of an individual mansion's rooms relationship.", + "operationId": "getMansionRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion whose related room identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found room identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/roomIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The mansion does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "mansions" + ], + "summary": "Retrieves the related room identities of an individual mansion's rooms relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headMansionRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion whose related room identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The mansion does not exist." + } + } + }, + "post": { + "tags": [ + "mansions" + ], + "summary": "Adds existing rooms to the rooms relationship of an individual mansion.", + "operationId": "postMansionRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion to add rooms to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the rooms to add to the rooms relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The rooms were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The mansion or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "mansions" + ], + "summary": "Assigns existing rooms to the rooms relationship of an individual mansion.", + "operationId": "patchMansionRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion whose rooms relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the rooms to assign to the rooms relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The rooms relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The mansion or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "mansions" + ], + "summary": "Removes existing rooms from the rooms relationship of an individual mansion.", + "operationId": "deleteMansionRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion to remove rooms from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the rooms to remove from the rooms relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The rooms were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The mansion or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/mansions/{id}/staff": { + "get": { + "tags": [ + "mansions" + ], + "summary": "Retrieves the related staffMembers of an individual mansion's staff relationship.", + "operationId": "getMansionStaff", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion whose related staffMembers to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found staffMembers, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/staffMemberCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The mansion does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "mansions" + ], + "summary": "Retrieves the related staffMembers of an individual mansion's staff relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headMansionStaff", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion whose related staffMembers to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The mansion does not exist." + } + } + } + }, + "/mansions/{id}/relationships/staff": { + "get": { + "tags": [ + "mansions" + ], + "summary": "Retrieves the related staffMember identities of an individual mansion's staff relationship.", + "operationId": "getMansionStaffRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion whose related staffMember identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found staffMember identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/staffMemberIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The mansion does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "mansions" + ], + "summary": "Retrieves the related staffMember identities of an individual mansion's staff relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headMansionStaffRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion whose related staffMember identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The mansion does not exist." + } + } + }, + "post": { + "tags": [ + "mansions" + ], + "summary": "Adds existing staffMembers to the staff relationship of an individual mansion.", + "operationId": "postMansionStaffRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion to add staffMembers to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the staffMembers to add to the staff relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStaffMemberInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The staffMembers were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The mansion or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "mansions" + ], + "summary": "Assigns existing staffMembers to the staff relationship of an individual mansion.", + "operationId": "patchMansionStaffRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion whose staff relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the staffMembers to assign to the staff relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStaffMemberInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The staff relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The mansion or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "mansions" + ], + "summary": "Removes existing staffMembers from the staff relationship of an individual mansion.", + "operationId": "deleteMansionStaffRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion to remove staffMembers from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the staffMembers to remove from the staff relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStaffMemberInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The staffMembers were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The mansion or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/operations": { + "post": { + "tags": [ + "operations" + ], + "summary": "Performs multiple mutations in a linear and atomic manner.", + "operationId": "postOperations", + "requestBody": { + "description": "An array of mutation operations. For syntax, see the [Atomic Operations documentation](https://jsonapi.org/ext/atomic/).", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/operationsRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "All operations were successfully applied, which resulted in additional changes.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/operationsResponseDocument" + } + } + } + }, + "204": { + "description": "All operations were successfully applied, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "An operation is not accessible or a client-generated ID is used.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/residences": { + "get": { + "tags": [ + "residences" + ], + "summary": "Retrieves a collection of residences.", + "operationId": "getResidenceCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found residences, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/residenceCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "residences" + ], + "summary": "Retrieves a collection of residences without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResidenceCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "residences" + ], + "summary": "Creates a new residence.", + "operationId": "postResidence", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the residence to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createResidenceRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The residence was successfully created, which resulted in additional changes. The newly created residence is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created residence can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryResidenceResponseDocument" + } + } + } + }, + "204": { + "description": "The residence was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/residences/{id}": { + "get": { + "tags": [ + "residences" + ], + "summary": "Retrieves an individual residence by its identifier.", + "operationId": "getResidence", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the residence to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found residence.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryResidenceResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The residence does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "residences" + ], + "summary": "Retrieves an individual residence by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResidence", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the residence to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The residence does not exist." + } + } + }, + "patch": { + "tags": [ + "residences" + ], + "summary": "Updates an existing residence.", + "operationId": "patchResidence", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the residence to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the residence to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateResidenceRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The residence was successfully updated, which resulted in additional changes. The updated residence is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryResidenceResponseDocument" + } + } + } + }, + "204": { + "description": "The residence was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The residence or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "residences" + ], + "summary": "Deletes an existing residence by its identifier.", + "operationId": "deleteResidence", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the residence to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "The residence was successfully deleted." + }, + "404": { + "description": "The residence does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/residences/{id}/rooms": { + "get": { + "tags": [ + "residences" + ], + "summary": "Retrieves the related rooms of an individual residence's rooms relationship.", + "operationId": "getResidenceRooms", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the residence whose related rooms to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found rooms, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/roomCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The residence does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "residences" + ], + "summary": "Retrieves the related rooms of an individual residence's rooms relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResidenceRooms", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the residence whose related rooms to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The residence does not exist." + } + } + } + }, + "/residences/{id}/relationships/rooms": { + "get": { + "tags": [ + "residences" + ], + "summary": "Retrieves the related room identities of an individual residence's rooms relationship.", + "operationId": "getResidenceRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the residence whose related room identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found room identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/roomIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The residence does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "residences" + ], + "summary": "Retrieves the related room identities of an individual residence's rooms relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResidenceRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the residence whose related room identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The residence does not exist." + } + } + }, + "post": { + "tags": [ + "residences" + ], + "summary": "Adds existing rooms to the rooms relationship of an individual residence.", + "operationId": "postResidenceRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the residence to add rooms to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the rooms to add to the rooms relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The rooms were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The residence or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "residences" + ], + "summary": "Assigns existing rooms to the rooms relationship of an individual residence.", + "operationId": "patchResidenceRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the residence whose rooms relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the rooms to assign to the rooms relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The rooms relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The residence or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "residences" + ], + "summary": "Removes existing rooms from the rooms relationship of an individual residence.", + "operationId": "deleteResidenceRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the residence to remove rooms from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the rooms to remove from the rooms relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The rooms were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The residence or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/roads": { + "get": { + "tags": [ + "roads" + ], + "summary": "Retrieves a collection of roads.", + "operationId": "getRoadCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found roads, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/roadCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "roads" + ], + "summary": "Retrieves a collection of roads without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headRoadCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "roads" + ], + "summary": "Creates a new road.", + "operationId": "postRoad", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the road to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createRoadRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The road was successfully created, which resulted in additional changes. The newly created road is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created road can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryRoadResponseDocument" + } + } + } + }, + "204": { + "description": "The road was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/roads/{id}": { + "get": { + "tags": [ + "roads" + ], + "summary": "Retrieves an individual road by its identifier.", + "operationId": "getRoad", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the road to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found road.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryRoadResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The road does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "roads" + ], + "summary": "Retrieves an individual road by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headRoad", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the road to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The road does not exist." + } + } + }, + "patch": { + "tags": [ + "roads" + ], + "summary": "Updates an existing road.", + "operationId": "patchRoad", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the road to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the road to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateRoadRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The road was successfully updated, which resulted in additional changes. The updated road is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryRoadResponseDocument" + } + } + } + }, + "204": { + "description": "The road was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The road or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "roads" + ], + "summary": "Deletes an existing road by its identifier.", + "operationId": "deleteRoad", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the road to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "The road was successfully deleted." + }, + "404": { + "description": "The road does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/rooms": { + "get": { + "tags": [ + "rooms" + ], + "summary": "Retrieves a collection of rooms.", + "operationId": "getRoomCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found rooms, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/roomCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "rooms" + ], + "summary": "Retrieves a collection of rooms without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headRoomCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "rooms" + ], + "summary": "Creates a new room.", + "operationId": "postRoom", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the room to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createRoomRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The room was successfully created, which resulted in additional changes. The newly created room is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created room can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryRoomResponseDocument" + } + } + } + }, + "204": { + "description": "The room was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/rooms/{id}": { + "get": { + "tags": [ + "rooms" + ], + "summary": "Retrieves an individual room by its identifier.", + "operationId": "getRoom", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the room to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found room.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryRoomResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The room does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "rooms" + ], + "summary": "Retrieves an individual room by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headRoom", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the room to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The room does not exist." + } + } + }, + "patch": { + "tags": [ + "rooms" + ], + "summary": "Updates an existing room.", + "operationId": "patchRoom", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the room to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the room to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateRoomRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The room was successfully updated, which resulted in additional changes. The updated room is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryRoomResponseDocument" + } + } + } + }, + "204": { + "description": "The room was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The room or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "rooms" + ], + "summary": "Deletes an existing room by its identifier.", + "operationId": "deleteRoom", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the room to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "The room was successfully deleted." + }, + "404": { + "description": "The room does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/rooms/{id}/residence": { + "get": { + "tags": [ + "rooms" + ], + "summary": "Retrieves the related residence of an individual room's residence relationship.", + "operationId": "getRoomResidence", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the room whose related residence to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found residence, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/secondaryResidenceResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The room does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "rooms" + ], + "summary": "Retrieves the related residence of an individual room's residence relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headRoomResidence", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the room whose related residence to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The room does not exist." + } + } + } + }, + "/rooms/{id}/relationships/residence": { + "get": { + "tags": [ + "rooms" + ], + "summary": "Retrieves the related residence identity of an individual room's residence relationship.", + "operationId": "getRoomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the room whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found residence identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/residenceIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The room does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "rooms" + ], + "summary": "Retrieves the related residence identity of an individual room's residence relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headRoomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the room whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The room does not exist." + } + } + }, + "patch": { + "tags": [ + "rooms" + ], + "summary": "Assigns an existing residence to the residence relationship of an individual room.", + "operationId": "patchRoomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the room whose residence relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identity of the residence to assign to the residence relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneResidenceInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The residence relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The room or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/staffMembers": { + "get": { + "tags": [ + "staffMembers" + ], + "summary": "Retrieves a collection of staffMembers.", + "operationId": "getStaffMemberCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found staffMembers, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/staffMemberCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "staffMembers" + ], + "summary": "Retrieves a collection of staffMembers without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headStaffMemberCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "staffMembers" + ], + "summary": "Creates a new staffMember.", + "operationId": "postStaffMember", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the staffMember to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createStaffMemberRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The staffMember was successfully created, which resulted in additional changes. The newly created staffMember is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created staffMember can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryStaffMemberResponseDocument" + } + } + } + }, + "204": { + "description": "The staffMember was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/staffMembers/{id}": { + "get": { + "tags": [ + "staffMembers" + ], + "summary": "Retrieves an individual staffMember by its identifier.", + "operationId": "getStaffMember", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the staffMember to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found staffMember.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryStaffMemberResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The staffMember does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "staffMembers" + ], + "summary": "Retrieves an individual staffMember by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headStaffMember", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the staffMember to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The staffMember does not exist." + } + } + }, + "patch": { + "tags": [ + "staffMembers" + ], + "summary": "Updates an existing staffMember.", + "operationId": "patchStaffMember", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the staffMember to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the staffMember to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateStaffMemberRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The staffMember was successfully updated, which resulted in additional changes. The updated staffMember is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryStaffMemberResponseDocument" + } + } + } + }, + "204": { + "description": "The staffMember was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The staffMember or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "staffMembers" + ], + "summary": "Deletes an existing staffMember by its identifier.", + "operationId": "deleteStaffMember", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the staffMember to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "The staffMember was successfully deleted." + }, + "404": { + "description": "The staffMember does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/toilets": { + "get": { + "tags": [ + "toilets" + ], + "summary": "Retrieves a collection of toilets.", + "operationId": "getToiletCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found toilets, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/toiletCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "toilets" + ], + "summary": "Retrieves a collection of toilets without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headToiletCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + }, + "post": { + "tags": [ + "toilets" + ], + "summary": "Creates a new toilet.", + "operationId": "postToilet", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the toilet to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createToiletRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The toilet was successfully created, which resulted in additional changes. The newly created toilet is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created toilet can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryToiletResponseDocument" + } + } + } + }, + "204": { + "description": "The toilet was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/toilets/{id}": { + "get": { + "tags": [ + "toilets" + ], + "summary": "Retrieves an individual toilet by its identifier.", + "operationId": "getToilet", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the toilet to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found toilet.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryToiletResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The toilet does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "toilets" + ], + "summary": "Retrieves an individual toilet by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headToilet", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the toilet to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The toilet does not exist." + } + } + }, + "patch": { + "tags": [ + "toilets" + ], + "summary": "Updates an existing toilet.", + "operationId": "patchToilet", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the toilet to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the toilet to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateToiletRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The toilet was successfully updated, which resulted in additional changes. The updated toilet is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryToiletResponseDocument" + } + } + } + }, + "204": { + "description": "The toilet was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The toilet or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "toilets" + ], + "summary": "Deletes an existing toilet by its identifier.", + "operationId": "deleteToilet", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the toilet to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "The toilet was successfully deleted." + }, + "404": { + "description": "The toilet does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/toilets/{id}/residence": { + "get": { + "tags": [ + "toilets" + ], + "summary": "Retrieves the related residence of an individual toilet's residence relationship.", + "operationId": "getToiletResidence", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the toilet whose related residence to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found residence, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/secondaryResidenceResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The toilet does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "toilets" + ], + "summary": "Retrieves the related residence of an individual toilet's residence relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headToiletResidence", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the toilet whose related residence to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The toilet does not exist." + } + } + } + }, + "/toilets/{id}/relationships/residence": { + "get": { + "tags": [ + "toilets" + ], + "summary": "Retrieves the related residence identity of an individual toilet's residence relationship.", + "operationId": "getToiletResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the toilet whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found residence identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/residenceIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The toilet does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "toilets" + ], + "summary": "Retrieves the related residence identity of an individual toilet's residence relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headToiletResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the toilet whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The toilet does not exist." + } + } + }, + "patch": { + "tags": [ + "toilets" + ], + "summary": "Assigns an existing residence to the residence relationship of an individual toilet.", + "operationId": "patchToiletResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the toilet whose residence relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identity of the residence to assign to the residence relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneResidenceInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The residence relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The toilet or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "atomicOperation": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "type": "string" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator" + }, + "x-abstract": true + }, + "atomicResult": { + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "attributesInBathroomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInRoomResponse" + }, + { + "type": "object", + "properties": { + "hasBath": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInBedroomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInRoomResponse" + }, + { + "type": "object", + "properties": { + "bedCount": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInBuildingResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "surfaceInSquareMeters": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "familyHomes": "#/components/schemas/attributesInFamilyHomeResponse", + "mansions": "#/components/schemas/attributesInMansionResponse", + "residences": "#/components/schemas/attributesInResidenceResponse" + } + }, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "attributesInCreateBathroomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRoomRequest" + }, + { + "required": [ + "hasBath" + ], + "type": "object", + "properties": { + "hasBath": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateBedroomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRoomRequest" + }, + { + "required": [ + "bedCount" + ], + "type": "object", + "properties": { + "bedCount": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateBuildingRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "surfaceInSquareMeters" + ], + "type": "object", + "properties": { + "surfaceInSquareMeters": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "attributesInCreateCyclePathRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRoadRequest" + }, + { + "type": "object", + "properties": { + "hasLaneForPedestrians": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateDistrictRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateFamilyHomeRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateResidenceRequest" + }, + { + "type": "object", + "properties": { + "floorCount": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateKitchenRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRoomRequest" + }, + { + "required": [ + "hasPantry" + ], + "type": "object", + "properties": { + "hasPantry": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateLivingRoomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRoomRequest" + }, + { + "required": [ + "hasDiningTable" + ], + "type": "object", + "properties": { + "hasDiningTable": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateMansionRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateResidenceRequest" + }, + { + "required": [ + "ownerName" + ], + "type": "object", + "properties": { + "ownerName": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "bathrooms": "#/components/schemas/attributesInCreateBathroomRequest", + "bedrooms": "#/components/schemas/attributesInCreateBedroomRequest", + "buildings": "#/components/schemas/attributesInCreateBuildingRequest", + "cyclePaths": "#/components/schemas/attributesInCreateCyclePathRequest", + "districts": "#/components/schemas/attributesInCreateDistrictRequest", + "familyHomes": "#/components/schemas/attributesInCreateFamilyHomeRequest", + "kitchens": "#/components/schemas/attributesInCreateKitchenRequest", + "livingRooms": "#/components/schemas/attributesInCreateLivingRoomRequest", + "mansions": "#/components/schemas/attributesInCreateMansionRequest", + "residences": "#/components/schemas/attributesInCreateResidenceRequest", + "roads": "#/components/schemas/attributesInCreateRoadRequest", + "rooms": "#/components/schemas/attributesInCreateRoomRequest", + "staffMembers": "#/components/schemas/attributesInCreateStaffMemberRequest", + "toilets": "#/components/schemas/attributesInCreateToiletRequest" + } + }, + "x-abstract": true + }, + "attributesInCreateResidenceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateBuildingRequest" + }, + { + "required": [ + "numberOfResidents" + ], + "type": "object", + "properties": { + "numberOfResidents": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateRoadRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "type": "object", + "properties": { + "lengthInMeters": { + "type": "number", + "format": "double" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateRoomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "surfaceInSquareMeters" + ], + "type": "object", + "properties": { + "surfaceInSquareMeters": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "attributesInCreateStaffMemberRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateToiletRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRoomRequest" + }, + { + "required": [ + "hasSink" + ], + "type": "object", + "properties": { + "hasSink": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCyclePathResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInRoadResponse" + }, + { + "type": "object", + "properties": { + "hasLaneForPedestrians": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInDistrictResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInFamilyHomeResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResidenceResponse" + }, + { + "type": "object", + "properties": { + "floorCount": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInKitchenResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInRoomResponse" + }, + { + "type": "object", + "properties": { + "hasPantry": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInLivingRoomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInRoomResponse" + }, + { + "type": "object", + "properties": { + "hasDiningTable": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInMansionResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResidenceResponse" + }, + { + "type": "object", + "properties": { + "ownerName": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInResidenceResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInBuildingResponse" + }, + { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "numberOfResidents": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "familyHomes": "#/components/schemas/attributesInFamilyHomeResponse", + "mansions": "#/components/schemas/attributesInMansionResponse" + } + } + } + ], + "additionalProperties": false + }, + "attributesInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "bathrooms": "#/components/schemas/attributesInBathroomResponse", + "bedrooms": "#/components/schemas/attributesInBedroomResponse", + "buildings": "#/components/schemas/attributesInBuildingResponse", + "cyclePaths": "#/components/schemas/attributesInCyclePathResponse", + "districts": "#/components/schemas/attributesInDistrictResponse", + "familyHomes": "#/components/schemas/attributesInFamilyHomeResponse", + "kitchens": "#/components/schemas/attributesInKitchenResponse", + "livingRooms": "#/components/schemas/attributesInLivingRoomResponse", + "mansions": "#/components/schemas/attributesInMansionResponse", + "residences": "#/components/schemas/attributesInResidenceResponse", + "roads": "#/components/schemas/attributesInRoadResponse", + "rooms": "#/components/schemas/attributesInRoomResponse", + "staffMembers": "#/components/schemas/attributesInStaffMemberResponse", + "toilets": "#/components/schemas/attributesInToiletResponse" + } + }, + "x-abstract": true + }, + "attributesInRoadResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "lengthInMeters": { + "type": "number", + "format": "double" + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "cyclePaths": "#/components/schemas/attributesInCyclePathResponse" + } + } + } + ], + "additionalProperties": false + }, + "attributesInRoomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "surfaceInSquareMeters": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "bathrooms": "#/components/schemas/attributesInBathroomResponse", + "bedrooms": "#/components/schemas/attributesInBedroomResponse", + "kitchens": "#/components/schemas/attributesInKitchenResponse", + "livingRooms": "#/components/schemas/attributesInLivingRoomResponse", + "toilets": "#/components/schemas/attributesInToiletResponse" + } + }, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "attributesInStaffMemberResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInToiletResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInRoomResponse" + }, + { + "type": "object", + "properties": { + "hasSink": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateBathroomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRoomRequest" + }, + { + "type": "object", + "properties": { + "hasBath": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateBedroomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRoomRequest" + }, + { + "type": "object", + "properties": { + "bedCount": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateBuildingRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "surfaceInSquareMeters": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "attributesInUpdateCyclePathRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRoadRequest" + }, + { + "type": "object", + "properties": { + "hasLaneForPedestrians": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateDistrictRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateFamilyHomeRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateResidenceRequest" + }, + { + "type": "object", + "properties": { + "floorCount": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateKitchenRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRoomRequest" + }, + { + "type": "object", + "properties": { + "hasPantry": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateLivingRoomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRoomRequest" + }, + { + "type": "object", + "properties": { + "hasDiningTable": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateMansionRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateResidenceRequest" + }, + { + "type": "object", + "properties": { + "ownerName": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "bathrooms": "#/components/schemas/attributesInUpdateBathroomRequest", + "bedrooms": "#/components/schemas/attributesInUpdateBedroomRequest", + "buildings": "#/components/schemas/attributesInUpdateBuildingRequest", + "cyclePaths": "#/components/schemas/attributesInUpdateCyclePathRequest", + "districts": "#/components/schemas/attributesInUpdateDistrictRequest", + "familyHomes": "#/components/schemas/attributesInUpdateFamilyHomeRequest", + "kitchens": "#/components/schemas/attributesInUpdateKitchenRequest", + "livingRooms": "#/components/schemas/attributesInUpdateLivingRoomRequest", + "mansions": "#/components/schemas/attributesInUpdateMansionRequest", + "residences": "#/components/schemas/attributesInUpdateResidenceRequest", + "roads": "#/components/schemas/attributesInUpdateRoadRequest", + "rooms": "#/components/schemas/attributesInUpdateRoomRequest", + "staffMembers": "#/components/schemas/attributesInUpdateStaffMemberRequest", + "toilets": "#/components/schemas/attributesInUpdateToiletRequest" + } + }, + "x-abstract": true + }, + "attributesInUpdateResidenceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateBuildingRequest" + }, + { + "type": "object", + "properties": { + "numberOfResidents": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateRoadRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "lengthInMeters": { + "type": "number", + "format": "double" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateRoomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "surfaceInSquareMeters": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "attributesInUpdateStaffMemberRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateToiletRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRoomRequest" + }, + { + "type": "object", + "properties": { + "hasSink": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "bathroomCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInBathroomResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "bathroomIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "bathroomIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "bedroomCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInBedroomResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "bedroomIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "bedroomIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "buildingCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInBuildingResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "buildingIdentifierCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/buildingIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "buildingIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "buildingIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/buildingResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "familyHomes": "#/components/schemas/familyHomeIdentifierInResponse", + "mansions": "#/components/schemas/mansionIdentifierInResponse", + "residences": "#/components/schemas/residenceIdentifierInResponse" + } + }, + "x-abstract": true + }, + "buildingResourceType": { + "enum": [ + "familyHomes", + "mansions", + "residences" + ], + "type": "string" + }, + "createBathroomRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateBathroomRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "createBedroomRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateBedroomRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "createBuildingRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateBuildingRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "createCyclePathRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateCyclePathRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "createDistrictRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateDistrictRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "createFamilyHomeRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateFamilyHomeRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "createKitchenRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateKitchenRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "createLivingRoomRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateLivingRoomRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "createMansionRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateMansionRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "createResidenceRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateResidenceRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "createRoadRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateRoadRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "createRoomRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateRoomRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "createStaffMemberRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateStaffMemberRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "createToiletRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateToiletRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "cyclePathCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInCyclePathResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "cyclePathIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/roadIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "cyclePathIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/roadIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInBathroomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInBedroomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInBuildingResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInBuildingResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInBuildingResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "familyHomes": "#/components/schemas/dataInFamilyHomeResponse", + "mansions": "#/components/schemas/dataInMansionResponse", + "residences": "#/components/schemas/dataInResidenceResponse" + } + }, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "dataInCreateBathroomRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateBedroomRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateBuildingRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateBuildingRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateBuildingRequest" + } + ] + } + }, + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "dataInCreateCyclePathRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateRoadRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateDistrictRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateDistrictRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateDistrictRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateFamilyHomeRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateResidenceRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateKitchenRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateLivingRoomRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateMansionRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateResidenceRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateResidenceRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateBuildingRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateRoadRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRoadRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRoadRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateRoomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRoomRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRoomRequest" + } + ] + } + }, + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "dataInCreateStaffMemberRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateStaffMemberRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateToiletRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCyclePathResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInRoadResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInDistrictResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInDistrictResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInDistrictResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInFamilyHomeResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInResidenceResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInKitchenResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInLivingRoomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInMansionResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInResidenceResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInResidenceResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInBuildingResponse" + }, + { + "required": [ + "type" + ], + "type": "object", + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "familyHomes": "#/components/schemas/dataInFamilyHomeResponse", + "mansions": "#/components/schemas/dataInMansionResponse" + } + } + } + ], + "additionalProperties": false + }, + "dataInRoadResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInRoadResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInRoadResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "cyclePaths": "#/components/schemas/dataInCyclePathResponse" + } + } + } + ], + "additionalProperties": false + }, + "dataInRoomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInRoomResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInRoomResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "bathrooms": "#/components/schemas/dataInBathroomResponse", + "bedrooms": "#/components/schemas/dataInBedroomResponse", + "kitchens": "#/components/schemas/dataInKitchenResponse", + "livingRooms": "#/components/schemas/dataInLivingRoomResponse", + "toilets": "#/components/schemas/dataInToiletResponse" + } + }, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "dataInStaffMemberResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInStaffMemberResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInToiletResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateBathroomRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateBedroomRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateBuildingRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateBuildingRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateBuildingRequest" + } + ] + } + }, + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "dataInUpdateCyclePathRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateRoadRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateDistrictRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateDistrictRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateDistrictRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateFamilyHomeRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateResidenceRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateKitchenRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateLivingRoomRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateMansionRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateResidenceRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateResidenceRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateBuildingRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateRoadRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRoadRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRoadRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateRoomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRoomRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRoomRequest" + } + ] + } + }, + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "dataInUpdateStaffMemberRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateStaffMemberRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateToiletRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "districtCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInDistrictResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorLinks": { + "type": "object", + "properties": { + "about": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorObject": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorLinks" + } + ], + "nullable": true + }, + "status": { + "type": "string" + }, + "code": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/errorSource" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorResponseDocument": { + "required": [ + "errors", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorTopLevelLinks" + } + ] + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/errorObject" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorSource": { + "type": "object", + "properties": { + "pointer": { + "type": "string", + "nullable": true + }, + "parameter": { + "type": "string", + "nullable": true + }, + "header": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "familyHomeCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInFamilyHomeResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "familyHomeIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "familyHomeIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "identifierInRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "bathrooms": "#/components/schemas/bathroomIdentifierInRequest", + "bedrooms": "#/components/schemas/bedroomIdentifierInRequest", + "buildings": "#/components/schemas/buildingIdentifierInRequest", + "cyclePaths": "#/components/schemas/cyclePathIdentifierInRequest", + "familyHomes": "#/components/schemas/familyHomeIdentifierInRequest", + "kitchens": "#/components/schemas/kitchenIdentifierInRequest", + "livingRooms": "#/components/schemas/livingRoomIdentifierInRequest", + "mansions": "#/components/schemas/mansionIdentifierInRequest", + "residences": "#/components/schemas/residenceIdentifierInRequest", + "roads": "#/components/schemas/roadIdentifierInRequest", + "rooms": "#/components/schemas/roomIdentifierInRequest", + "staffMembers": "#/components/schemas/staffMemberIdentifierInRequest", + "toilets": "#/components/schemas/toiletIdentifierInRequest" + } + }, + "x-abstract": true + }, + "kitchenCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInKitchenResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "kitchenIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "kitchenIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "livingRoomCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInLivingRoomResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "livingRoomIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "livingRoomIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "mansionCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInMansionResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "mansionIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "mansionIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "meta": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "operationsRequestDocument": { + "required": [ + "atomic:operations" + ], + "type": "object", + "properties": { + "atomic:operations": { + "minItems": 1, + "type": "array", + "items": { + "$ref": "#/components/schemas/atomicOperation" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "operationsResponseDocument": { + "required": [ + "atomic:results", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "atomic:results": { + "minItems": 1, + "type": "array", + "items": { + "$ref": "#/components/schemas/atomicResult" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryBathroomResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInBathroomResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryBedroomResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInBedroomResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryBuildingResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInBuildingResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryCyclePathResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCyclePathResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryDistrictResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInDistrictResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryFamilyHomeResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInFamilyHomeResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryKitchenResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInKitchenResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryLivingRoomResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInLivingRoomResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryMansionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInMansionResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryResidenceResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInResidenceResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryRoadResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInRoadResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryRoomResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInRoomResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryStaffMemberResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInStaffMemberResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryToiletResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInToiletResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "relationshipLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + } + }, + "additionalProperties": false + }, + "relationshipsInBathroomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInBedroomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInBuildingResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "familyHomes": "#/components/schemas/relationshipsInFamilyHomeResponse", + "mansions": "#/components/schemas/relationshipsInMansionResponse", + "residences": "#/components/schemas/relationshipsInResidenceResponse" + } + }, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "relationshipsInCreateBathroomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateBedroomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateBuildingRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "type": "object", + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "relationshipsInCreateCyclePathRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRoadRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateDistrictRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "type": "object", + "properties": { + "buildings": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyBuildingInRequest" + } + ] + }, + "roads": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoadInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateFamilyHomeRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateResidenceRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateKitchenRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateLivingRoomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateMansionRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateResidenceRequest" + }, + { + "type": "object", + "properties": { + "staff": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStaffMemberInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "bathrooms": "#/components/schemas/relationshipsInCreateBathroomRequest", + "bedrooms": "#/components/schemas/relationshipsInCreateBedroomRequest", + "buildings": "#/components/schemas/relationshipsInCreateBuildingRequest", + "cyclePaths": "#/components/schemas/relationshipsInCreateCyclePathRequest", + "districts": "#/components/schemas/relationshipsInCreateDistrictRequest", + "familyHomes": "#/components/schemas/relationshipsInCreateFamilyHomeRequest", + "kitchens": "#/components/schemas/relationshipsInCreateKitchenRequest", + "livingRooms": "#/components/schemas/relationshipsInCreateLivingRoomRequest", + "mansions": "#/components/schemas/relationshipsInCreateMansionRequest", + "residences": "#/components/schemas/relationshipsInCreateResidenceRequest", + "roads": "#/components/schemas/relationshipsInCreateRoadRequest", + "rooms": "#/components/schemas/relationshipsInCreateRoomRequest", + "toilets": "#/components/schemas/relationshipsInCreateToiletRequest" + } + }, + "x-abstract": true + }, + "relationshipsInCreateResidenceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateBuildingRequest" + }, + { + "type": "object", + "properties": { + "rooms": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateRoadRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateRoomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "required": [ + "residence" + ], + "type": "object", + "properties": { + "residence": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneResidenceInRequest" + } + ] + } + }, + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "relationshipsInCreateToiletRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCyclePathResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInRoadResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInDistrictResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "type": "object", + "properties": { + "buildings": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyBuildingInResponse" + } + ] + }, + "roads": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoadInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInFamilyHomeResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResidenceResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInKitchenResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInLivingRoomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInMansionResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResidenceResponse" + }, + { + "type": "object", + "properties": { + "staff": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStaffMemberInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInResidenceResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInBuildingResponse" + }, + { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "rooms": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInResponse" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "familyHomes": "#/components/schemas/relationshipsInFamilyHomeResponse", + "mansions": "#/components/schemas/relationshipsInMansionResponse" + } + } + } + ], + "additionalProperties": false + }, + "relationshipsInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "bathrooms": "#/components/schemas/relationshipsInBathroomResponse", + "bedrooms": "#/components/schemas/relationshipsInBedroomResponse", + "buildings": "#/components/schemas/relationshipsInBuildingResponse", + "cyclePaths": "#/components/schemas/relationshipsInCyclePathResponse", + "districts": "#/components/schemas/relationshipsInDistrictResponse", + "familyHomes": "#/components/schemas/relationshipsInFamilyHomeResponse", + "kitchens": "#/components/schemas/relationshipsInKitchenResponse", + "livingRooms": "#/components/schemas/relationshipsInLivingRoomResponse", + "mansions": "#/components/schemas/relationshipsInMansionResponse", + "residences": "#/components/schemas/relationshipsInResidenceResponse", + "roads": "#/components/schemas/relationshipsInRoadResponse", + "rooms": "#/components/schemas/relationshipsInRoomResponse", + "toilets": "#/components/schemas/relationshipsInToiletResponse" + } + }, + "x-abstract": true + }, + "relationshipsInRoadResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "cyclePaths": "#/components/schemas/relationshipsInCyclePathResponse" + } + } + } + ], + "additionalProperties": false + }, + "relationshipsInRoomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "residence": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneResidenceInResponse" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "bathrooms": "#/components/schemas/relationshipsInBathroomResponse", + "bedrooms": "#/components/schemas/relationshipsInBedroomResponse", + "kitchens": "#/components/schemas/relationshipsInKitchenResponse", + "livingRooms": "#/components/schemas/relationshipsInLivingRoomResponse", + "toilets": "#/components/schemas/relationshipsInToiletResponse" + } + }, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "relationshipsInToiletResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateBathroomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateBedroomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateBuildingRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateCyclePathRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRoadRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateDistrictRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "buildings": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyBuildingInRequest" + } + ] + }, + "roads": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoadInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateFamilyHomeRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateResidenceRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateKitchenRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateLivingRoomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateMansionRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateResidenceRequest" + }, + { + "type": "object", + "properties": { + "staff": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStaffMemberInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "bathrooms": "#/components/schemas/relationshipsInUpdateBathroomRequest", + "bedrooms": "#/components/schemas/relationshipsInUpdateBedroomRequest", + "buildings": "#/components/schemas/relationshipsInUpdateBuildingRequest", + "cyclePaths": "#/components/schemas/relationshipsInUpdateCyclePathRequest", + "districts": "#/components/schemas/relationshipsInUpdateDistrictRequest", + "familyHomes": "#/components/schemas/relationshipsInUpdateFamilyHomeRequest", + "kitchens": "#/components/schemas/relationshipsInUpdateKitchenRequest", + "livingRooms": "#/components/schemas/relationshipsInUpdateLivingRoomRequest", + "mansions": "#/components/schemas/relationshipsInUpdateMansionRequest", + "residences": "#/components/schemas/relationshipsInUpdateResidenceRequest", + "roads": "#/components/schemas/relationshipsInUpdateRoadRequest", + "rooms": "#/components/schemas/relationshipsInUpdateRoomRequest", + "toilets": "#/components/schemas/relationshipsInUpdateToiletRequest" + } + }, + "x-abstract": true + }, + "relationshipsInUpdateResidenceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateBuildingRequest" + }, + { + "type": "object", + "properties": { + "rooms": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateRoadRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateRoomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "residence": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneResidenceInRequest" + } + ] + } + }, + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateToiletRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "residenceCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInResidenceResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "residenceIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/buildingIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "residenceIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/buildingIdentifierInResponse" + }, + { + "required": [ + "type" + ], + "type": "object", + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "familyHomes": "#/components/schemas/familyHomeIdentifierInResponse", + "mansions": "#/components/schemas/mansionIdentifierInResponse" + } + } + } + ], + "additionalProperties": false + }, + "residenceIdentifierResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "resourceCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceIdentifierCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceIdentifierTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceInCreateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "bathrooms": "#/components/schemas/dataInCreateBathroomRequest", + "bedrooms": "#/components/schemas/dataInCreateBedroomRequest", + "buildings": "#/components/schemas/dataInCreateBuildingRequest", + "cyclePaths": "#/components/schemas/dataInCreateCyclePathRequest", + "districts": "#/components/schemas/dataInCreateDistrictRequest", + "familyHomes": "#/components/schemas/dataInCreateFamilyHomeRequest", + "kitchens": "#/components/schemas/dataInCreateKitchenRequest", + "livingRooms": "#/components/schemas/dataInCreateLivingRoomRequest", + "mansions": "#/components/schemas/dataInCreateMansionRequest", + "residences": "#/components/schemas/dataInCreateResidenceRequest", + "roads": "#/components/schemas/dataInCreateRoadRequest", + "rooms": "#/components/schemas/dataInCreateRoomRequest", + "staffMembers": "#/components/schemas/dataInCreateStaffMemberRequest", + "toilets": "#/components/schemas/dataInCreateToiletRequest" + } + }, + "x-abstract": true + }, + "resourceInResponse": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "bathrooms": "#/components/schemas/dataInBathroomResponse", + "bedrooms": "#/components/schemas/dataInBedroomResponse", + "buildings": "#/components/schemas/dataInBuildingResponse", + "cyclePaths": "#/components/schemas/dataInCyclePathResponse", + "districts": "#/components/schemas/dataInDistrictResponse", + "familyHomes": "#/components/schemas/dataInFamilyHomeResponse", + "kitchens": "#/components/schemas/dataInKitchenResponse", + "livingRooms": "#/components/schemas/dataInLivingRoomResponse", + "mansions": "#/components/schemas/dataInMansionResponse", + "residences": "#/components/schemas/dataInResidenceResponse", + "roads": "#/components/schemas/dataInRoadResponse", + "rooms": "#/components/schemas/dataInRoomResponse", + "staffMembers": "#/components/schemas/dataInStaffMemberResponse", + "toilets": "#/components/schemas/dataInToiletResponse" + } + }, + "x-abstract": true + }, + "resourceInUpdateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "bathrooms": "#/components/schemas/dataInUpdateBathroomRequest", + "bedrooms": "#/components/schemas/dataInUpdateBedroomRequest", + "buildings": "#/components/schemas/dataInUpdateBuildingRequest", + "cyclePaths": "#/components/schemas/dataInUpdateCyclePathRequest", + "districts": "#/components/schemas/dataInUpdateDistrictRequest", + "familyHomes": "#/components/schemas/dataInUpdateFamilyHomeRequest", + "kitchens": "#/components/schemas/dataInUpdateKitchenRequest", + "livingRooms": "#/components/schemas/dataInUpdateLivingRoomRequest", + "mansions": "#/components/schemas/dataInUpdateMansionRequest", + "residences": "#/components/schemas/dataInUpdateResidenceRequest", + "roads": "#/components/schemas/dataInUpdateRoadRequest", + "rooms": "#/components/schemas/dataInUpdateRoomRequest", + "staffMembers": "#/components/schemas/dataInUpdateStaffMemberRequest", + "toilets": "#/components/schemas/dataInUpdateToiletRequest" + } + }, + "x-abstract": true + }, + "resourceLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceType": { + "enum": [ + "bathrooms", + "bedrooms", + "buildings", + "cyclePaths", + "districts", + "familyHomes", + "kitchens", + "livingRooms", + "mansions", + "residences", + "roads", + "rooms", + "staffMembers", + "toilets" + ], + "type": "string" + }, + "roadCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInRoadResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "roadIdentifierCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roadIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "roadIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "roadIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/roadResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "cyclePaths": "#/components/schemas/cyclePathIdentifierInResponse" + } + } + }, + "roadResourceType": { + "enum": [ + "cyclePaths", + "roads" + ], + "type": "string" + }, + "roomCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInRoomResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "roomIdentifierCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roomIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "roomIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "roomIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/roomResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "bathrooms": "#/components/schemas/bathroomIdentifierInResponse", + "bedrooms": "#/components/schemas/bedroomIdentifierInResponse", + "kitchens": "#/components/schemas/kitchenIdentifierInResponse", + "livingRooms": "#/components/schemas/livingRoomIdentifierInResponse", + "toilets": "#/components/schemas/toiletIdentifierInResponse" + } + }, + "x-abstract": true + }, + "roomResourceType": { + "enum": [ + "bathrooms", + "bedrooms", + "kitchens", + "livingRooms", + "toilets" + ], + "type": "string" + }, + "secondaryResidenceResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInResidenceResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "staffMemberCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInStaffMemberResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "staffMemberIdentifierCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staffMemberIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "staffMemberIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "staffMemberIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/staffMemberResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "staffMemberResourceType": { + "enum": [ + "staffMembers" + ], + "type": "string" + }, + "toManyBuildingInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/buildingIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyBuildingInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/buildingIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyRoadInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roadIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyRoadInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roadIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyRoomInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roomIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyRoomInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roomIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyStaffMemberInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staffMemberIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyStaffMemberInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staffMemberIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneResidenceInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneResidenceInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toiletCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInToiletResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toiletIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "toiletIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateBathroomRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateBathroomRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateBedroomRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateBedroomRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateBuildingRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateBuildingRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateCyclePathRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateCyclePathRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateDistrictRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateDistrictRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateFamilyHomeRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateFamilyHomeRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateKitchenRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateKitchenRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateLivingRoomRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateLivingRoomRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateMansionRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateMansionRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateResidenceRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateResidenceRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateRoadRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateRoadRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateRoomRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateRoomRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateStaffMemberRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateStaffMemberRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateToiletRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateToiletRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/test/OpenApiTests/ResourceInheritance/NoOperations/NoOperationsEndpointFilter.cs b/test/OpenApiTests/ResourceInheritance/NoOperations/NoOperationsEndpointFilter.cs new file mode 100644 index 0000000000..5b2866d074 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/NoOperations/NoOperationsEndpointFilter.cs @@ -0,0 +1,13 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; + +namespace OpenApiTests.ResourceInheritance.NoOperations; + +public sealed class NoOperationsEndpointFilter : IJsonApiEndpointFilter +{ + public bool IsEnabled(ResourceType resourceType, JsonApiEndpoints endpoint) + { + return true; + } +} diff --git a/test/OpenApiTests/ResourceInheritance/NoOperations/NoOperationsInheritanceTests.cs b/test/OpenApiTests/ResourceInheritance/NoOperations/NoOperationsInheritanceTests.cs new file mode 100644 index 0000000000..c057fdacc7 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/NoOperations/NoOperationsInheritanceTests.cs @@ -0,0 +1,333 @@ +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; +using Microsoft.Extensions.DependencyInjection; +using OpenApiTests.ResourceInheritance.Models; +using Xunit; +using Xunit.Abstractions; + +#pragma warning disable format + +namespace OpenApiTests.ResourceInheritance.NoOperations; + +public sealed class NoOperationsInheritanceTests : ResourceInheritanceTests +{ + public NoOperationsInheritanceTests(OpenApiTestContext, ResourceInheritanceDbContext> testContext, + ITestOutputHelper testOutputHelper) + : base(testContext, testOutputHelper, true, true) + { + testContext.ConfigureServices(services => + { + services.AddSingleton(); + services.AddSingleton(); + }); + } + + [Theory] + [InlineData(typeof(District), JsonApiEndpoints.All)] + [InlineData(typeof(StaffMember), JsonApiEndpoints.All)] + [InlineData(typeof(Building), JsonApiEndpoints.All)] + [InlineData(typeof(Residence), JsonApiEndpoints.All)] + [InlineData(typeof(FamilyHome), JsonApiEndpoints.All)] + [InlineData(typeof(Mansion), JsonApiEndpoints.All)] + [InlineData(typeof(Room), JsonApiEndpoints.All)] + [InlineData(typeof(Kitchen), JsonApiEndpoints.All)] + [InlineData(typeof(Bedroom), JsonApiEndpoints.All)] + [InlineData(typeof(Bathroom), JsonApiEndpoints.All)] + [InlineData(typeof(LivingRoom), JsonApiEndpoints.All)] + [InlineData(typeof(Toilet), JsonApiEndpoints.All)] + [InlineData(typeof(Road), JsonApiEndpoints.All)] + [InlineData(typeof(CyclePath), JsonApiEndpoints.All)] + public override async Task Only_expected_endpoints_are_exposed(Type resourceClrType, JsonApiEndpoints expected) + { + await base.Only_expected_endpoints_are_exposed(resourceClrType, expected); + } + + [Theory] + [InlineData(true)] + public override async Task Operations_endpoint_is_exposed(bool enabled) + { + await base.Operations_endpoint_is_exposed(enabled); + } + + [Theory] + [InlineData("resourceInCreateRequest", false, + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|districts|roads|cyclePaths|staffMembers")] + [InlineData("resourceInUpdateRequest", false, + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|districts|roads|cyclePaths|staffMembers")] + [InlineData("identifierInRequest", false, + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|roads|cyclePaths|staffMembers")] + [InlineData("resourceInResponse", false, + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|districts|roads|cyclePaths|staffMembers")] + [InlineData("dataInBuildingResponse", true, "familyHomes|mansions|residences")] + [InlineData("buildingIdentifierInResponse", false, "familyHomes|mansions|residences")] + [InlineData("dataInResidenceResponse", true, "familyHomes|mansions")] + [InlineData("residenceIdentifierInResponse", true, "familyHomes|mansions")] + [InlineData("dataInRoomResponse", true, "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("roomIdentifierInResponse", false, "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("dataInRoadResponse", true, "cyclePaths")] + [InlineData("roadIdentifierInResponse", false, "cyclePaths")] + public override async Task Expected_names_appear_in_type_discriminator_mapping(string schemaName, bool isWrapped, string? discriminatorValues) + { + await base.Expected_names_appear_in_type_discriminator_mapping(schemaName, isWrapped, discriminatorValues); + } + + [Theory] + [InlineData("attributesInCreateRequest", + "familyHomes|mansions|residences|buildings|bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|cyclePaths|roads|districts|staffMembers")] + [InlineData("attributesInUpdateRequest", + "familyHomes|mansions|residences|buildings|bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|cyclePaths|roads|districts|staffMembers")] + [InlineData("relationshipsInCreateRequest", + "familyHomes|mansions|residences|buildings|bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|cyclePaths|roads|districts")] + [InlineData("relationshipsInUpdateRequest", + "familyHomes|mansions|residences|buildings|bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|cyclePaths|roads|districts")] + [InlineData("!attributesInBuildingResponse", "familyHomes|mansions|residences")] + [InlineData("!relationshipsInBuildingResponse", "familyHomes|mansions|residences")] + [InlineData("!attributesInRoomResponse", "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("!relationshipsInRoomResponse", "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("!attributesInRoadResponse", "cyclePaths")] + [InlineData("!relationshipsInRoadResponse", "cyclePaths")] + [InlineData("atomicOperation", "")] + public override async Task Expected_names_appear_in_openapi_discriminator_mapping(string schemaName, string? discriminatorValues) + { + await base.Expected_names_appear_in_openapi_discriminator_mapping(schemaName, discriminatorValues); + } + + [Theory] + [InlineData("buildingResourceType", "familyHomes|mansions|residences")] + [InlineData("residenceResourceType", null)] + [InlineData("familyHomeResourceType", null)] + [InlineData("mansionResourceType", null)] + [InlineData("roomResourceType", "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("bathroomResourceType", null)] + [InlineData("bedroomResourceType", null)] + [InlineData("kitchenResourceType", null)] + [InlineData("livingRoomResourceType", null)] + [InlineData("toiletResourceType", null)] + [InlineData("roadResourceType", "roads|cyclePaths")] + [InlineData("cyclePathResourceType", null)] + [InlineData("districtResourceType", null)] + [InlineData("staffMemberResourceType", "staffMembers")] + [InlineData("resourceType", + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|roads|cyclePaths|districts|staffMembers")] + public override async Task Expected_names_appear_in_resource_type_enum(string schemaName, string? enumValues) + { + await base.Expected_names_appear_in_resource_type_enum(schemaName, enumValues); + } + + [Theory] + [InlineData("resourceInCreateRequest", true, null, "type|meta")] + [InlineData("attributesInCreateRequest", true, null, "openapi:discriminator")] + [InlineData("relationshipsInCreateRequest", true, null, "openapi:discriminator")] + [InlineData("resourceInUpdateRequest", true, null, "type|meta")] + [InlineData("attributesInUpdateRequest", true, null, "openapi:discriminator")] + [InlineData("relationshipsInUpdateRequest", true, null, "openapi:discriminator")] + [InlineData("identifierInRequest", true, null, "type|meta")] + [InlineData("resourceInResponse", true, null, "type|meta")] + [InlineData("atomicOperation", true, null, "openapi:discriminator|meta")] + // Building hierarchy: Resource Data + [InlineData("dataInCreateBuildingRequest", true, "resourceInCreateRequest", "lid|attributes|relationships")] + [InlineData("dataInCreateResidenceRequest", false, "dataInCreateBuildingRequest", null)] + [InlineData("dataInCreateFamilyHomeRequest", false, "dataInCreateResidenceRequest", null)] + [InlineData("dataInCreateMansionRequest", false, "dataInCreateResidenceRequest", null)] + [InlineData("dataInUpdateBuildingRequest", true, "resourceInUpdateRequest", "id|lid|attributes|relationships")] + [InlineData("dataInUpdateResidenceRequest", false, "dataInUpdateBuildingRequest", null)] + [InlineData("dataInUpdateFamilyHomeRequest", false, "dataInUpdateResidenceRequest", null)] + [InlineData("dataInUpdateMansionRequest", false, "dataInUpdateResidenceRequest", null)] + [InlineData("dataInBuildingResponse", true, "resourceInResponse", "id|attributes|relationships|links")] + [InlineData("dataInResidenceResponse", false, "dataInBuildingResponse", null)] + [InlineData("dataInFamilyHomeResponse", false, "dataInResidenceResponse", null)] + [InlineData("dataInMansionResponse", false, "dataInResidenceResponse", null)] + // Building hierarchy: Attributes + [InlineData("attributesInCreateBuildingRequest", true, "attributesInCreateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInCreateResidenceRequest", false, "attributesInCreateBuildingRequest", "numberOfResidents")] + [InlineData("attributesInCreateFamilyHomeRequest", false, "attributesInCreateResidenceRequest", "floorCount")] + [InlineData("attributesInCreateMansionRequest", false, "attributesInCreateResidenceRequest", "ownerName")] + [InlineData("attributesInUpdateBuildingRequest", true, "attributesInUpdateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInUpdateResidenceRequest", false, "attributesInUpdateBuildingRequest", "numberOfResidents")] + [InlineData("attributesInUpdateFamilyHomeRequest", false, "attributesInUpdateResidenceRequest", "floorCount")] + [InlineData("attributesInUpdateMansionRequest", false, "attributesInUpdateResidenceRequest", "ownerName")] + [InlineData("attributesInBuildingResponse", true, "attributesInResponse", "surfaceInSquareMeters")] + [InlineData("attributesInResidenceResponse", false, "attributesInBuildingResponse", "numberOfResidents")] + [InlineData("attributesInFamilyHomeResponse", false, "attributesInResidenceResponse", "floorCount")] + [InlineData("attributesInMansionResponse", false, "attributesInResidenceResponse", "ownerName")] + // Building hierarchy: Relationships + [InlineData("relationshipsInCreateBuildingRequest", true, "relationshipsInCreateRequest", null)] + [InlineData("relationshipsInCreateResidenceRequest", false, "relationshipsInCreateBuildingRequest", "rooms")] + [InlineData("relationshipsInCreateFamilyHomeRequest", false, "relationshipsInCreateResidenceRequest", null)] + [InlineData("relationshipsInCreateMansionRequest", false, "relationshipsInCreateResidenceRequest", "staff")] + [InlineData("relationshipsInUpdateBuildingRequest", true, "relationshipsInUpdateRequest", null)] + [InlineData("relationshipsInUpdateResidenceRequest", false, "relationshipsInUpdateBuildingRequest", "rooms")] + [InlineData("relationshipsInUpdateFamilyHomeRequest", false, "relationshipsInUpdateResidenceRequest", null)] + [InlineData("relationshipsInUpdateMansionRequest", false, "relationshipsInUpdateResidenceRequest", "staff")] + [InlineData("relationshipsInBuildingResponse", true, "relationshipsInResponse", null)] + [InlineData("relationshipsInResidenceResponse", false, "relationshipsInBuildingResponse", "rooms")] + [InlineData("relationshipsInFamilyHomeResponse", false, "relationshipsInResidenceResponse", null)] + [InlineData("relationshipsInMansionResponse", false, "relationshipsInResidenceResponse", "staff")] + // Building hierarchy: Resource Identifiers + [InlineData("buildingIdentifierInRequest", false, "identifierInRequest", "id|lid")] + [InlineData("residenceIdentifierInRequest", false, "buildingIdentifierInRequest", null)] + [InlineData("familyHomeIdentifierInRequest", false, "residenceIdentifierInRequest", null)] + [InlineData("mansionIdentifierInRequest", false, "residenceIdentifierInRequest", null)] + [InlineData("buildingIdentifierInResponse", true, null, "type|id|meta")] + [InlineData("residenceIdentifierInResponse", false, "buildingIdentifierInResponse", null)] + [InlineData("familyHomeIdentifierInResponse", false, "residenceIdentifierInResponse", null)] + [InlineData("mansionIdentifierInResponse", false, "residenceIdentifierInResponse", null)] + // Building hierarchy: Atomic Operations + [InlineData("createBuildingOperation", false, null, null)] + [InlineData("createResidenceOperation", false, null, null)] + [InlineData("createFamilyHomeOperation", false, null, null)] + [InlineData("createMansionOperation", false, null, null)] + [InlineData("updateBuildingOperation", false, null, null)] + [InlineData("updateResidenceOperation", false, null, null)] + [InlineData("updateFamilyHomeOperation", false, null, null)] + [InlineData("updateMansionOperation", false, null, null)] + [InlineData("deleteBuildingOperation", false, null, null)] + [InlineData("deleteResidenceOperation", false, null, null)] + [InlineData("deleteFamilyHomeOperation", false, null, null)] + [InlineData("deleteMansionOperation", false, null, null)] + [InlineData("updateResidenceRoomsRelationshipOperation", false, null, null)] + [InlineData("updateFamilyHomeRoomsRelationshipOperation", false, null, null)] + [InlineData("updateMansionRoomsRelationshipOperation", false, null, null)] + [InlineData("updateMansionStaffRelationshipOperation", false, null, null)] + [InlineData("addToResidenceRoomsRelationshipOperation", false, null, null)] + [InlineData("addToFamilyHomeRoomsRelationshipOperation", false, null, null)] + [InlineData("addToMansionRoomsRelationshipOperation", false, null, null)] + [InlineData("addToMansionStaffRelationshipOperation", false, null, null)] + [InlineData("removeFromResidenceRoomsRelationshipOperation", false, null, null)] + [InlineData("removeFromFamilyHomeRoomsRelationshipOperation", false, null, null)] + [InlineData("removeFromMansionRoomsRelationshipOperation", false, null, null)] + [InlineData("removeFromMansionStaffRelationshipOperation", false, null, null)] + // Room hierarchy: Resource Data + [InlineData("dataInCreateRoomRequest", true, "resourceInCreateRequest", "lid|attributes|relationships")] + [InlineData("dataInCreateBathroomRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateBedroomRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateKitchenRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateLivingRoomRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateToiletRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInUpdateRoomRequest", true, "resourceInUpdateRequest", "id|lid|attributes|relationships")] + [InlineData("dataInUpdateBathroomRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInUpdateBedroomRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInUpdateKitchenRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInUpdateLivingRoomRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInUpdateToiletRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInRoomResponse", true, "resourceInResponse", "id|attributes|relationships|links")] + [InlineData("dataInBathroomResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInBedroomResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInKitchenResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInLivingRoomResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInToiletResponse", false, "dataInRoomResponse", null)] + // Room hierarchy: Attributes + [InlineData("attributesInCreateRoomRequest", true, "attributesInCreateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInCreateBathroomRequest", false, "attributesInCreateRoomRequest", "hasBath")] + [InlineData("attributesInCreateBedroomRequest", false, "attributesInCreateRoomRequest", "bedCount")] + [InlineData("attributesInCreateKitchenRequest", false, "attributesInCreateRoomRequest", "hasPantry")] + [InlineData("attributesInCreateLivingRoomRequest", false, "attributesInCreateRoomRequest", "hasDiningTable")] + [InlineData("attributesInCreateToiletRequest", false, "attributesInCreateRoomRequest", "hasSink")] + [InlineData("attributesInUpdateRoomRequest", true, "attributesInUpdateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInUpdateBathroomRequest", false, "attributesInUpdateRoomRequest", "hasBath")] + [InlineData("attributesInUpdateBedroomRequest", false, "attributesInUpdateRoomRequest", "bedCount")] + [InlineData("attributesInUpdateKitchenRequest", false, "attributesInUpdateRoomRequest", "hasPantry")] + [InlineData("attributesInUpdateLivingRoomRequest", false, "attributesInUpdateRoomRequest", "hasDiningTable")] + [InlineData("attributesInUpdateToiletRequest", false, "attributesInUpdateRoomRequest", "hasSink")] + [InlineData("attributesInRoomResponse", true, "attributesInResponse", "surfaceInSquareMeters")] + [InlineData("attributesInBathroomResponse", false, "attributesInRoomResponse", "hasBath")] + [InlineData("attributesInBedroomResponse", false, "attributesInRoomResponse", "bedCount")] + [InlineData("attributesInKitchenResponse", false, "attributesInRoomResponse", "hasPantry")] + [InlineData("attributesInLivingRoomResponse", false, "attributesInRoomResponse", "hasDiningTable")] + [InlineData("attributesInToiletResponse", false, "attributesInRoomResponse", "hasSink")] + // Room hierarchy: Relationships + [InlineData("relationshipsInCreateRoomRequest", true, "relationshipsInCreateRequest", "residence")] + [InlineData("relationshipsInCreateBathroomRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateBedroomRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateKitchenRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateLivingRoomRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateToiletRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInUpdateRoomRequest", true, "relationshipsInUpdateRequest", "residence")] + [InlineData("relationshipsInUpdateBathroomRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInUpdateBedroomRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInUpdateKitchenRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInUpdateLivingRoomRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInUpdateToiletRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInRoomResponse", true, "relationshipsInResponse", "residence")] + [InlineData("relationshipsInBathroomResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInBedroomResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInKitchenResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInLivingRoomResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInToiletResponse", false, "relationshipsInRoomResponse", null)] + // Room hierarchy: Resource Identifiers + [InlineData("roomIdentifierInRequest", false, "identifierInRequest", "id|lid")] + [InlineData("bathroomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("bedroomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("kitchenIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("livingRoomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("toiletIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("roomIdentifierInResponse", true, null, "type|id|meta")] + [InlineData("bathroomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("bedroomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("kitchenIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("livingRoomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("toiletIdentifierInResponse", false, "roomIdentifierInResponse", null)] + // Room hierarchy: Atomic Operations + [InlineData("createRoomOperation", false, null, null)] + [InlineData("createBathroomOperation", false, null, null)] + [InlineData("createBedroomOperation", false, null, null)] + [InlineData("createKitchenOperation", false, null, null)] + [InlineData("createLivingRoomOperation", false, null, null)] + [InlineData("createToiletOperation", false, null, null)] + [InlineData("updateRoomOperation", false, null, null)] + [InlineData("updateBathroomOperation", false, null, null)] + [InlineData("updateBedroomOperation", false, null, null)] + [InlineData("updateKitchenOperation", false, null, null)] + [InlineData("updateLivingRoomOperation", false, null, null)] + [InlineData("updateToiletOperation", false, null, null)] + [InlineData("deleteRoomOperation", false, null, null)] + [InlineData("deleteBathroomOperation", false, null, null)] + [InlineData("deleteBedroomOperation", false, null, null)] + [InlineData("deleteKitchenOperation", false, null, null)] + [InlineData("deleteLivingRoomOperation", false, null, null)] + [InlineData("deleteToiletOperation", false, null, null)] + [InlineData("updateRoomResidenceRelationshipOperation", false, null, null)] + [InlineData("updateBathroomResidenceRelationshipOperation", false, null, null)] + [InlineData("updateBedroomResidenceRelationshipOperation", false, null, null)] + [InlineData("updateKitchenResidenceRelationshipOperation", false, null, null)] + [InlineData("updateLivingRoomResidenceRelationshipOperation", false, null, null)] + [InlineData("updateToiletResidenceRelationshipOperation", false, null, null)] + // Road hierarchy: Resource Data + [InlineData("dataInCreateRoadRequest", false, "resourceInCreateRequest", "lid|attributes|relationships")] + [InlineData("dataInCreateCyclePathRequest", false, "dataInCreateRoadRequest", null)] + [InlineData("dataInUpdateRoadRequest", false, "resourceInUpdateRequest", "id|lid|attributes|relationships")] + [InlineData("dataInUpdateCyclePathRequest", false, "dataInUpdateRoadRequest", null)] + [InlineData("dataInRoadResponse", false, "resourceInResponse", "id|attributes|relationships|links")] + [InlineData("dataInCyclePathResponse", false, "dataInRoadResponse", null)] + // Road hierarchy: Attributes + [InlineData("attributesInCreateRoadRequest", false, "attributesInCreateRequest", "lengthInMeters")] + [InlineData("attributesInCreateCyclePathRequest", false, "attributesInCreateRoadRequest", "hasLaneForPedestrians")] + [InlineData("attributesInUpdateRoadRequest", false, "attributesInUpdateRequest", "lengthInMeters")] + [InlineData("attributesInUpdateCyclePathRequest", false, "attributesInUpdateRoadRequest", "hasLaneForPedestrians")] + [InlineData("attributesInRoadResponse", false, "attributesInResponse", "lengthInMeters")] + [InlineData("attributesInCyclePathResponse", false, "attributesInRoadResponse", "hasLaneForPedestrians")] + // Road hierarchy: Relationships + [InlineData("relationshipsInCreateRoadRequest", false, "relationshipsInCreateRequest", null)] + [InlineData("relationshipsInCreateCyclePathRequest", false, "relationshipsInCreateRoadRequest", null)] + [InlineData("relationshipsInUpdateRoadRequest", false, "relationshipsInUpdateRequest", null)] + [InlineData("relationshipsInUpdateCyclePathRequest", false, "relationshipsInUpdateRoadRequest", null)] + [InlineData("relationshipsInRoadResponse", false, "relationshipsInResponse", null)] + [InlineData("relationshipsInCyclePathResponse", false, "relationshipsInRoadResponse", null)] + // Road hierarchy: Resource Identifiers + [InlineData("roadIdentifierInRequest", false, "identifierInRequest", "id|lid")] + [InlineData("cyclePathIdentifierInRequest", false, "roadIdentifierInRequest", null)] + [InlineData("roadIdentifierInResponse", false, null, "type|id|meta")] + [InlineData("cyclePathIdentifierInResponse", false, "roadIdentifierInResponse", null)] + // Road hierarchy: Atomic Operations + [InlineData("createRoadOperation", false, null, null)] + [InlineData("createCyclePathOperation", false, null, null)] + [InlineData("updateRoadOperation", false, null, null)] + [InlineData("updateCyclePathOperation", false, null, null)] + [InlineData("deleteRoadOperation", false, null, null)] + [InlineData("deleteCyclePathOperation", false, null, null)] + public override async Task Component_schemas_have_expected_base_type(string schemaName, bool isAbstract, string? baseType, string? properties) + { + await base.Component_schemas_have_expected_base_type(schemaName, isAbstract, baseType, properties); + } +} diff --git a/test/OpenApiTests/ResourceInheritance/NoOperations/NoOperationsOperationFilter.cs b/test/OpenApiTests/ResourceInheritance/NoOperations/NoOperationsOperationFilter.cs new file mode 100644 index 0000000000..4c4f63ef5e --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/NoOperations/NoOperationsOperationFilter.cs @@ -0,0 +1,13 @@ +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; + +namespace OpenApiTests.ResourceInheritance.NoOperations; + +public sealed class NoOperationsOperationFilter : DefaultOperationFilter +{ + protected override JsonApiEndpoints? GetJsonApiEndpoints(ResourceType resourceType) + { + return JsonApiEndpoints.None; + } +} diff --git a/test/OpenApiTests/ResourceInheritance/OnlyAbstract/OnlyAbstractEndpointFilter.cs b/test/OpenApiTests/ResourceInheritance/OnlyAbstract/OnlyAbstractEndpointFilter.cs new file mode 100644 index 0000000000..29d20e0ab8 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/OnlyAbstract/OnlyAbstractEndpointFilter.cs @@ -0,0 +1,13 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; + +namespace OpenApiTests.ResourceInheritance.OnlyAbstract; + +internal sealed class OnlyAbstractEndpointFilter : IJsonApiEndpointFilter +{ + public bool IsEnabled(ResourceType resourceType, JsonApiEndpoints endpoint) + { + return resourceType.ClrType.IsAbstract; + } +} diff --git a/test/OpenApiTests/ResourceInheritance/OnlyAbstract/OnlyAbstractInheritanceTests.cs b/test/OpenApiTests/ResourceInheritance/OnlyAbstract/OnlyAbstractInheritanceTests.cs new file mode 100644 index 0000000000..5efacb7f17 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/OnlyAbstract/OnlyAbstractInheritanceTests.cs @@ -0,0 +1,337 @@ +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; +using Microsoft.Extensions.DependencyInjection; +using OpenApiTests.ResourceInheritance.Models; +using Xunit; +using Xunit.Abstractions; + +#pragma warning disable format + +namespace OpenApiTests.ResourceInheritance.OnlyAbstract; + +public sealed class OnlyAbstractInheritanceTests : ResourceInheritanceTests +{ + public OnlyAbstractInheritanceTests(OpenApiTestContext, ResourceInheritanceDbContext> testContext, + ITestOutputHelper testOutputHelper) + : base(testContext, testOutputHelper, true, false) + { + testContext.ConfigureServices(services => + { + services.AddSingleton(); + services.AddSingleton(); + }); + } + + [Theory] + [InlineData(typeof(District), JsonApiEndpoints.None)] + [InlineData(typeof(StaffMember), JsonApiEndpoints.None)] + [InlineData(typeof(Building), JsonApiEndpoints.All)] + [InlineData(typeof(Residence), JsonApiEndpoints.None)] + [InlineData(typeof(FamilyHome), JsonApiEndpoints.None)] + [InlineData(typeof(Mansion), JsonApiEndpoints.None)] + [InlineData(typeof(Room), JsonApiEndpoints.All)] + [InlineData(typeof(Kitchen), JsonApiEndpoints.None)] + [InlineData(typeof(Bedroom), JsonApiEndpoints.None)] + [InlineData(typeof(Bathroom), JsonApiEndpoints.None)] + [InlineData(typeof(LivingRoom), JsonApiEndpoints.None)] + [InlineData(typeof(Toilet), JsonApiEndpoints.None)] + [InlineData(typeof(Road), JsonApiEndpoints.None)] + [InlineData(typeof(CyclePath), JsonApiEndpoints.None)] + public override async Task Only_expected_endpoints_are_exposed(Type resourceClrType, JsonApiEndpoints expected) + { + await base.Only_expected_endpoints_are_exposed(resourceClrType, expected); + } + + [Theory] + [InlineData(true)] + public override async Task Operations_endpoint_is_exposed(bool enabled) + { + await base.Operations_endpoint_is_exposed(enabled); + } + + [Theory] + [InlineData("resourceInCreateRequest", false, "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings")] + [InlineData("resourceInUpdateRequest", false, "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings")] + [InlineData("identifierInRequest", false, "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|staffMembers")] + [InlineData("resourceInResponse", false, "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|staffMembers")] + [InlineData("dataInBuildingResponse", true, "familyHomes|mansions|residences")] + [InlineData("buildingIdentifierInResponse", false, "familyHomes|mansions|residences")] + [InlineData("dataInResidenceResponse", true, "familyHomes|mansions")] + [InlineData("residenceIdentifierInResponse", true, "familyHomes|mansions")] + [InlineData("dataInRoomResponse", true, "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("roomIdentifierInResponse", false, "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("dataInRoadResponse", true, null)] + [InlineData("roadIdentifierInResponse", false, null)] + public override async Task Expected_names_appear_in_type_discriminator_mapping(string schemaName, bool isWrapped, string? discriminatorValues) + { + await base.Expected_names_appear_in_type_discriminator_mapping(schemaName, isWrapped, discriminatorValues); + } + + [Theory] + [InlineData("attributesInCreateRequest", "familyHomes|mansions|residences|buildings|bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms")] + [InlineData("attributesInUpdateRequest", "familyHomes|mansions|residences|buildings|bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms")] + [InlineData("relationshipsInCreateRequest", "familyHomes|mansions|residences|buildings|bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms")] + [InlineData("relationshipsInUpdateRequest", "familyHomes|mansions|residences|buildings|bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms")] + [InlineData("!attributesInBuildingResponse", "familyHomes|mansions|residences")] + [InlineData("!relationshipsInBuildingResponse", "familyHomes|mansions|residences")] + [InlineData("!attributesInRoomResponse", "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("!relationshipsInRoomResponse", "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("!attributesInRoadResponse", null)] + [InlineData("!relationshipsInRoadResponse", null)] + [InlineData("atomicOperation", + // @formatter:keep_existing_linebreaks true + "addBuilding|updateBuilding|removeBuilding|" + + "addResidence|updateResidence|removeResidence|addToResidenceRooms|updateResidenceRooms|removeFromResidenceRooms|" + + "addFamilyHome|updateFamilyHome|removeFamilyHome|addToFamilyHomeRooms|updateFamilyHomeRooms|removeFromFamilyHomeRooms|" + + "addMansion|updateMansion|removeMansion|addToMansionRooms|updateMansionRooms|removeFromMansionRooms|addToMansionStaff|updateMansionStaff|removeFromMansionStaff|" + + "addRoom|updateRoom|removeRoom|updateRoomResidence|" + + "addBathroom|updateBathroom|removeBathroom|updateBathroomResidence|" + + "addBedroom|updateBedroom|removeBedroom|updateBedroomResidence|" + + "addKitchen|updateKitchen|removeKitchen|updateKitchenResidence|" + + "addLivingRoom|updateLivingRoom|removeLivingRoom|updateLivingRoomResidence|" + + "addToilet|updateToilet|removeToilet|updateToiletResidence" + // @formatter:keep_existing_linebreaks restore + )] + public override async Task Expected_names_appear_in_openapi_discriminator_mapping(string schemaName, string? discriminatorValues) + { + await base.Expected_names_appear_in_openapi_discriminator_mapping(schemaName, discriminatorValues); + } + + [Theory] + [InlineData("buildingResourceType", "familyHomes|mansions|residences")] + [InlineData("residenceResourceType", "familyHomes|mansions|residences")] + [InlineData("familyHomeResourceType", null)] + [InlineData("mansionResourceType", "mansions")] + [InlineData("roomResourceType", "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("bathroomResourceType", null)] + [InlineData("bedroomResourceType", null)] + [InlineData("kitchenResourceType", null)] + [InlineData("livingRoomResourceType", null)] + [InlineData("toiletResourceType", null)] + [InlineData("roadResourceType", null)] + [InlineData("cyclePathResourceType", null)] + [InlineData("districtResourceType", null)] + [InlineData("staffMemberResourceType", "staffMembers")] + [InlineData("resourceType", "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|staffMembers")] + public override async Task Expected_names_appear_in_resource_type_enum(string schemaName, string? enumValues) + { + await base.Expected_names_appear_in_resource_type_enum(schemaName, enumValues); + } + + [Theory] + [InlineData("resourceInCreateRequest", true, null, "type|meta")] + [InlineData("attributesInCreateRequest", true, null, "openapi:discriminator")] + [InlineData("relationshipsInCreateRequest", true, null, "openapi:discriminator")] + [InlineData("resourceInUpdateRequest", true, null, "type|meta")] + [InlineData("attributesInUpdateRequest", true, null, "openapi:discriminator")] + [InlineData("relationshipsInUpdateRequest", true, null, "openapi:discriminator")] + [InlineData("identifierInRequest", true, null, "type|meta")] + [InlineData("resourceInResponse", true, null, "type|meta")] + [InlineData("atomicOperation", true, null, "openapi:discriminator|meta")] + // Building hierarchy: Resource Data + [InlineData("dataInCreateBuildingRequest", true, "resourceInCreateRequest", "lid|attributes|relationships")] + [InlineData("dataInCreateResidenceRequest", false, "dataInCreateBuildingRequest", null)] + [InlineData("dataInCreateFamilyHomeRequest", false, "dataInCreateResidenceRequest", null)] + [InlineData("dataInCreateMansionRequest", false, "dataInCreateResidenceRequest", null)] + [InlineData("dataInUpdateBuildingRequest", true, "resourceInUpdateRequest", "id|lid|attributes|relationships")] + [InlineData("dataInUpdateResidenceRequest", false, "dataInUpdateBuildingRequest", null)] + [InlineData("dataInUpdateFamilyHomeRequest", false, "dataInUpdateResidenceRequest", null)] + [InlineData("dataInUpdateMansionRequest", false, "dataInUpdateResidenceRequest", null)] + [InlineData("dataInBuildingResponse", true, "resourceInResponse", "id|attributes|relationships|links")] + [InlineData("dataInResidenceResponse", false, "dataInBuildingResponse", null)] + [InlineData("dataInFamilyHomeResponse", false, "dataInResidenceResponse", null)] + [InlineData("dataInMansionResponse", false, "dataInResidenceResponse", null)] + // Building hierarchy: Attributes + [InlineData("attributesInCreateBuildingRequest", true, "attributesInCreateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInCreateResidenceRequest", false, "attributesInCreateBuildingRequest", "numberOfResidents")] + [InlineData("attributesInCreateFamilyHomeRequest", false, "attributesInCreateResidenceRequest", "floorCount")] + [InlineData("attributesInCreateMansionRequest", false, "attributesInCreateResidenceRequest", "ownerName")] + [InlineData("attributesInUpdateBuildingRequest", true, "attributesInUpdateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInUpdateResidenceRequest", false, "attributesInUpdateBuildingRequest", "numberOfResidents")] + [InlineData("attributesInUpdateFamilyHomeRequest", false, "attributesInUpdateResidenceRequest", "floorCount")] + [InlineData("attributesInUpdateMansionRequest", false, "attributesInUpdateResidenceRequest", "ownerName")] + [InlineData("attributesInBuildingResponse", true, "attributesInResponse", "surfaceInSquareMeters")] + [InlineData("attributesInResidenceResponse", false, "attributesInBuildingResponse", "numberOfResidents")] + [InlineData("attributesInFamilyHomeResponse", false, "attributesInResidenceResponse", "floorCount")] + [InlineData("attributesInMansionResponse", false, "attributesInResidenceResponse", "ownerName")] + // Building hierarchy: Relationships + [InlineData("relationshipsInCreateBuildingRequest", true, "relationshipsInCreateRequest", null)] + [InlineData("relationshipsInCreateResidenceRequest", false, "relationshipsInCreateBuildingRequest", "rooms")] + [InlineData("relationshipsInCreateFamilyHomeRequest", false, "relationshipsInCreateResidenceRequest", null)] + [InlineData("relationshipsInCreateMansionRequest", false, "relationshipsInCreateResidenceRequest", "staff")] + [InlineData("relationshipsInUpdateBuildingRequest", true, "relationshipsInUpdateRequest", null)] + [InlineData("relationshipsInUpdateResidenceRequest", false, "relationshipsInUpdateBuildingRequest", "rooms")] + [InlineData("relationshipsInUpdateFamilyHomeRequest", false, "relationshipsInUpdateResidenceRequest", null)] + [InlineData("relationshipsInUpdateMansionRequest", false, "relationshipsInUpdateResidenceRequest", "staff")] + [InlineData("relationshipsInBuildingResponse", true, "relationshipsInResponse", null)] + [InlineData("relationshipsInResidenceResponse", false, "relationshipsInBuildingResponse", "rooms")] + [InlineData("relationshipsInFamilyHomeResponse", false, "relationshipsInResidenceResponse", null)] + [InlineData("relationshipsInMansionResponse", false, "relationshipsInResidenceResponse", "staff")] + // Building hierarchy: Resource Identifiers + [InlineData("buildingIdentifierInRequest", false, "identifierInRequest", "id|lid")] + [InlineData("residenceIdentifierInRequest", false, "buildingIdentifierInRequest", null)] + [InlineData("familyHomeIdentifierInRequest", false, "residenceIdentifierInRequest", null)] + [InlineData("mansionIdentifierInRequest", false, "residenceIdentifierInRequest", null)] + [InlineData("buildingIdentifierInResponse", true, null, "type|id|meta")] + [InlineData("residenceIdentifierInResponse", false, "buildingIdentifierInResponse", null)] + [InlineData("familyHomeIdentifierInResponse", false, "residenceIdentifierInResponse", null)] + [InlineData("mansionIdentifierInResponse", false, "residenceIdentifierInResponse", null)] + // Building hierarchy: Atomic Operations + [InlineData("createBuildingOperation", false, "atomicOperation", "op|data")] + [InlineData("createResidenceOperation", false, "createBuildingOperation", null)] + [InlineData("createFamilyHomeOperation", false, "createResidenceOperation", null)] + [InlineData("createMansionOperation", false, "createResidenceOperation", null)] + [InlineData("updateBuildingOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateResidenceOperation", false, "updateBuildingOperation", null)] + [InlineData("updateFamilyHomeOperation", false, "updateResidenceOperation", null)] + [InlineData("updateMansionOperation", false, "updateResidenceOperation", null)] + [InlineData("deleteBuildingOperation", false, "atomicOperation", "op|ref")] + [InlineData("deleteResidenceOperation", false, "deleteBuildingOperation", null)] + [InlineData("deleteFamilyHomeOperation", false, "deleteResidenceOperation", null)] + [InlineData("deleteMansionOperation", false, "deleteResidenceOperation", null)] + [InlineData("updateResidenceRoomsRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateFamilyHomeRoomsRelationshipOperation", false, "updateResidenceRoomsRelationshipOperation", null)] + [InlineData("updateMansionRoomsRelationshipOperation", false, "updateResidenceRoomsRelationshipOperation", null)] + [InlineData("updateMansionStaffRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("addToResidenceRoomsRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("addToFamilyHomeRoomsRelationshipOperation", false, "addToResidenceRoomsRelationshipOperation", null)] + [InlineData("addToMansionRoomsRelationshipOperation", false, "addToResidenceRoomsRelationshipOperation", null)] + [InlineData("addToMansionStaffRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("removeFromResidenceRoomsRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("removeFromFamilyHomeRoomsRelationshipOperation", false, "removeFromResidenceRoomsRelationshipOperation", null)] + [InlineData("removeFromMansionRoomsRelationshipOperation", false, "removeFromResidenceRoomsRelationshipOperation", null)] + [InlineData("removeFromMansionStaffRelationshipOperation", false, "atomicOperation", "op|ref|data")] + // Room hierarchy: Resource Data + [InlineData("dataInCreateRoomRequest", true, "resourceInCreateRequest", "lid|attributes|relationships")] + [InlineData("dataInCreateBathroomRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateBedroomRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateKitchenRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateLivingRoomRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateToiletRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInUpdateRoomRequest", true, "resourceInUpdateRequest", "id|lid|attributes|relationships")] + [InlineData("dataInUpdateBathroomRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInUpdateBedroomRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInUpdateKitchenRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInUpdateLivingRoomRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInUpdateToiletRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInRoomResponse", true, "resourceInResponse", "id|attributes|relationships|links")] + [InlineData("dataInBathroomResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInBedroomResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInKitchenResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInLivingRoomResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInToiletResponse", false, "dataInRoomResponse", null)] + // Room hierarchy: Attributes + [InlineData("attributesInCreateRoomRequest", true, "attributesInCreateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInCreateBathroomRequest", false, "attributesInCreateRoomRequest", "hasBath")] + [InlineData("attributesInCreateBedroomRequest", false, "attributesInCreateRoomRequest", "bedCount")] + [InlineData("attributesInCreateKitchenRequest", false, "attributesInCreateRoomRequest", "hasPantry")] + [InlineData("attributesInCreateLivingRoomRequest", false, "attributesInCreateRoomRequest", "hasDiningTable")] + [InlineData("attributesInCreateToiletRequest", false, "attributesInCreateRoomRequest", "hasSink")] + [InlineData("attributesInUpdateRoomRequest", true, "attributesInUpdateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInUpdateBathroomRequest", false, "attributesInUpdateRoomRequest", "hasBath")] + [InlineData("attributesInUpdateBedroomRequest", false, "attributesInUpdateRoomRequest", "bedCount")] + [InlineData("attributesInUpdateKitchenRequest", false, "attributesInUpdateRoomRequest", "hasPantry")] + [InlineData("attributesInUpdateLivingRoomRequest", false, "attributesInUpdateRoomRequest", "hasDiningTable")] + [InlineData("attributesInUpdateToiletRequest", false, "attributesInUpdateRoomRequest", "hasSink")] + [InlineData("attributesInRoomResponse", true, "attributesInResponse", "surfaceInSquareMeters")] + [InlineData("attributesInBathroomResponse", false, "attributesInRoomResponse", "hasBath")] + [InlineData("attributesInBedroomResponse", false, "attributesInRoomResponse", "bedCount")] + [InlineData("attributesInKitchenResponse", false, "attributesInRoomResponse", "hasPantry")] + [InlineData("attributesInLivingRoomResponse", false, "attributesInRoomResponse", "hasDiningTable")] + [InlineData("attributesInToiletResponse", false, "attributesInRoomResponse", "hasSink")] + // Room hierarchy: Relationships + [InlineData("relationshipsInCreateRoomRequest", true, "relationshipsInCreateRequest", "residence")] + [InlineData("relationshipsInCreateBathroomRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateBedroomRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateKitchenRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateLivingRoomRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateToiletRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInUpdateRoomRequest", true, "relationshipsInUpdateRequest", "residence")] + [InlineData("relationshipsInUpdateBathroomRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInUpdateBedroomRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInUpdateKitchenRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInUpdateLivingRoomRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInUpdateToiletRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInRoomResponse", true, "relationshipsInResponse", "residence")] + [InlineData("relationshipsInBathroomResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInBedroomResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInKitchenResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInLivingRoomResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInToiletResponse", false, "relationshipsInRoomResponse", null)] + // Room hierarchy: Resource Identifiers + [InlineData("roomIdentifierInRequest", false, "identifierInRequest", "id|lid")] + [InlineData("bathroomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("bedroomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("kitchenIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("livingRoomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("toiletIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("roomIdentifierInResponse", true, null, "type|id|meta")] + [InlineData("bathroomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("bedroomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("kitchenIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("livingRoomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("toiletIdentifierInResponse", false, "roomIdentifierInResponse", null)] + // Room hierarchy: Atomic Operations + [InlineData("createRoomOperation", false, "atomicOperation", "op|data")] + [InlineData("createBathroomOperation", false, "createRoomOperation", null)] + [InlineData("createBedroomOperation", false, "createRoomOperation", null)] + [InlineData("createKitchenOperation", false, "createRoomOperation", null)] + [InlineData("createLivingRoomOperation", false, "createRoomOperation", null)] + [InlineData("createToiletOperation", false, "createRoomOperation", null)] + [InlineData("updateRoomOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateBathroomOperation", false, "updateRoomOperation", null)] + [InlineData("updateBedroomOperation", false, "updateRoomOperation", null)] + [InlineData("updateKitchenOperation", false, "updateRoomOperation", null)] + [InlineData("updateLivingRoomOperation", false, "updateRoomOperation", null)] + [InlineData("updateToiletOperation", false, "updateRoomOperation", null)] + [InlineData("deleteRoomOperation", false, "atomicOperation", "op|ref")] + [InlineData("deleteBathroomOperation", false, "deleteRoomOperation", null)] + [InlineData("deleteBedroomOperation", false, "deleteRoomOperation", null)] + [InlineData("deleteKitchenOperation", false, "deleteRoomOperation", null)] + [InlineData("deleteLivingRoomOperation", false, "deleteRoomOperation", null)] + [InlineData("deleteToiletOperation", false, "deleteRoomOperation", null)] + [InlineData("updateRoomResidenceRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateBathroomResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + [InlineData("updateBedroomResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + [InlineData("updateKitchenResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + [InlineData("updateLivingRoomResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + [InlineData("updateToiletResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + // Road hierarchy: Resource Data + [InlineData("dataInCreateRoadRequest", false, null, null)] + [InlineData("dataInCreateCyclePathRequest", false, null, null)] + [InlineData("dataInUpdateRoadRequest", false, null, null)] + [InlineData("dataInUpdateCyclePathRequest", false, null, null)] + [InlineData("dataInRoadResponse", false, null, null)] + [InlineData("dataInCyclePathResponse", false, null, null)] + // Road hierarchy: Attributes + [InlineData("attributesInCreateRoadRequest", false, null, null)] + [InlineData("attributesInCreateCyclePathRequest", false, null, null)] + [InlineData("attributesInUpdateRoadRequest", false, null, null)] + [InlineData("attributesInUpdateCyclePathRequest", false, null, null)] + [InlineData("attributesInRoadResponse", false, null, null)] + [InlineData("attributesInCyclePathResponse", false, null, null)] + // Road hierarchy: Relationships + [InlineData("relationshipsInCreateRoadRequest", false, null, null)] + [InlineData("relationshipsInCreateCyclePathRequest", false, null, null)] + [InlineData("relationshipsInUpdateRoadRequest", false, null, null)] + [InlineData("relationshipsInUpdateCyclePathRequest", false, null, null)] + [InlineData("relationshipsInRoadResponse", false, null, null)] + [InlineData("relationshipsInCyclePathResponse", false, null, null)] + // Road hierarchy: Resource Identifiers + [InlineData("roadIdentifierInRequest", false, null, null)] + [InlineData("cyclePathIdentifierInRequest", false, null, null)] + [InlineData("roadIdentifierInResponse", false, null, null)] + [InlineData("cyclePathIdentifierInResponse", false, null, null)] + // Road hierarchy: Atomic Operations + [InlineData("createRoadOperation", false, null, null)] + [InlineData("createCyclePathOperation", false, null, null)] + [InlineData("updateRoadOperation", false, null, null)] + [InlineData("updateCyclePathOperation", false, null, null)] + [InlineData("deleteRoadOperation", false, null, null)] + [InlineData("deleteCyclePathOperation", false, null, null)] + public override async Task Component_schemas_have_expected_base_type(string schemaName, bool isAbstract, string? baseType, string? properties) + { + await base.Component_schemas_have_expected_base_type(schemaName, isAbstract, baseType, properties); + } +} diff --git a/test/OpenApiTests/ResourceInheritance/OnlyAbstract/OnlyAbstractOperationFilter.cs b/test/OpenApiTests/ResourceInheritance/OnlyAbstract/OnlyAbstractOperationFilter.cs new file mode 100644 index 0000000000..3031856a70 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/OnlyAbstract/OnlyAbstractOperationFilter.cs @@ -0,0 +1,13 @@ +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; + +namespace OpenApiTests.ResourceInheritance.OnlyAbstract; + +public sealed class OnlyAbstractOperationFilter : DefaultOperationFilter +{ + protected override JsonApiEndpoints? GetJsonApiEndpoints(ResourceType resourceType) + { + return resourceType.ClrType.IsAbstract ? JsonApiEndpoints.All : JsonApiEndpoints.None; + } +} diff --git a/test/OpenApiTests/ResourceInheritance/OnlyConcrete/OnlyConcreteEndpointFilter.cs b/test/OpenApiTests/ResourceInheritance/OnlyConcrete/OnlyConcreteEndpointFilter.cs new file mode 100644 index 0000000000..d12808f9c7 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/OnlyConcrete/OnlyConcreteEndpointFilter.cs @@ -0,0 +1,13 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; + +namespace OpenApiTests.ResourceInheritance.OnlyConcrete; + +internal sealed class OnlyConcreteEndpointFilter : IJsonApiEndpointFilter +{ + public bool IsEnabled(ResourceType resourceType, JsonApiEndpoints endpoint) + { + return !resourceType.ClrType.IsAbstract; + } +} diff --git a/test/OpenApiTests/ResourceInheritance/OnlyConcrete/OnlyConcreteInheritanceTests.cs b/test/OpenApiTests/ResourceInheritance/OnlyConcrete/OnlyConcreteInheritanceTests.cs new file mode 100644 index 0000000000..6a0f9742df --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/OnlyConcrete/OnlyConcreteInheritanceTests.cs @@ -0,0 +1,348 @@ +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; +using Microsoft.Extensions.DependencyInjection; +using OpenApiTests.ResourceInheritance.Models; +using Xunit; +using Xunit.Abstractions; + +#pragma warning disable format + +namespace OpenApiTests.ResourceInheritance.OnlyConcrete; + +public sealed class OnlyConcreteInheritanceTests : ResourceInheritanceTests +{ + public OnlyConcreteInheritanceTests(OpenApiTestContext, ResourceInheritanceDbContext> testContext, + ITestOutputHelper testOutputHelper) + : base(testContext, testOutputHelper, true, false) + { + testContext.ConfigureServices(services => + { + services.AddSingleton(); + services.AddSingleton(); + }); + } + + [Theory] + [InlineData(typeof(District), JsonApiEndpoints.All)] + [InlineData(typeof(StaffMember), JsonApiEndpoints.All)] + [InlineData(typeof(Building), JsonApiEndpoints.None)] + [InlineData(typeof(Residence), JsonApiEndpoints.All)] + [InlineData(typeof(FamilyHome), JsonApiEndpoints.All)] + [InlineData(typeof(Mansion), JsonApiEndpoints.All)] + [InlineData(typeof(Room), JsonApiEndpoints.None)] + [InlineData(typeof(Kitchen), JsonApiEndpoints.All)] + [InlineData(typeof(Bedroom), JsonApiEndpoints.All)] + [InlineData(typeof(Bathroom), JsonApiEndpoints.All)] + [InlineData(typeof(LivingRoom), JsonApiEndpoints.All)] + [InlineData(typeof(Toilet), JsonApiEndpoints.All)] + [InlineData(typeof(Road), JsonApiEndpoints.All)] + [InlineData(typeof(CyclePath), JsonApiEndpoints.All)] + public override async Task Only_expected_endpoints_are_exposed(Type resourceClrType, JsonApiEndpoints expected) + { + await base.Only_expected_endpoints_are_exposed(resourceClrType, expected); + } + + [Theory] + [InlineData(true)] + public override async Task Operations_endpoint_is_exposed(bool enabled) + { + await base.Operations_endpoint_is_exposed(enabled); + } + + [Theory] + [InlineData("resourceInCreateRequest", false, + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|districts|roads|cyclePaths|staffMembers")] + [InlineData("resourceInUpdateRequest", false, + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|districts|roads|cyclePaths|staffMembers")] + [InlineData("identifierInRequest", false, + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|districts|roads|cyclePaths|staffMembers")] + [InlineData("resourceInResponse", false, + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|districts|roads|cyclePaths|staffMembers")] + [InlineData("dataInBuildingResponse", true, "familyHomes|mansions|residences")] + [InlineData("buildingIdentifierInResponse", false, "familyHomes|mansions|residences")] + [InlineData("dataInResidenceResponse", true, "familyHomes|mansions")] + [InlineData("residenceIdentifierInResponse", true, "familyHomes|mansions")] + [InlineData("dataInRoomResponse", true, "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("roomIdentifierInResponse", false, "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("dataInRoadResponse", true, "cyclePaths")] + [InlineData("roadIdentifierInResponse", false, "cyclePaths")] + public override async Task Expected_names_appear_in_type_discriminator_mapping(string schemaName, bool isWrapped, string? discriminatorValues) + { + await base.Expected_names_appear_in_type_discriminator_mapping(schemaName, isWrapped, discriminatorValues); + } + + [Theory] + [InlineData("attributesInCreateRequest", + "familyHomes|mansions|residences|buildings|bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|cyclePaths|roads|districts|staffMembers")] + [InlineData("attributesInUpdateRequest", + "familyHomes|mansions|residences|buildings|bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|cyclePaths|roads|districts|staffMembers")] + [InlineData("relationshipsInCreateRequest", + "familyHomes|mansions|residences|buildings|bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|cyclePaths|roads|districts")] + [InlineData("relationshipsInUpdateRequest", + "familyHomes|mansions|residences|buildings|bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|cyclePaths|roads|districts")] + [InlineData("!attributesInBuildingResponse", "familyHomes|mansions|residences")] + [InlineData("!relationshipsInBuildingResponse", "familyHomes|mansions|residences")] + [InlineData("!attributesInRoomResponse", "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("!relationshipsInRoomResponse", "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("!attributesInRoadResponse", "cyclePaths")] + [InlineData("!relationshipsInRoadResponse", "cyclePaths")] + [InlineData("atomicOperation", + // @formatter:keep_existing_linebreaks true + "addResidence|updateResidence|removeResidence|addToResidenceRooms|updateResidenceRooms|removeFromResidenceRooms|" + + "addFamilyHome|updateFamilyHome|removeFamilyHome|addToFamilyHomeRooms|updateFamilyHomeRooms|removeFromFamilyHomeRooms|" + + "addMansion|updateMansion|removeMansion|addToMansionRooms|updateMansionRooms|removeFromMansionRooms|addToMansionStaff|updateMansionStaff|removeFromMansionStaff|" + + "addBathroom|updateBathroom|removeBathroom|updateBathroomResidence|" + + "addBedroom|updateBedroom|removeBedroom|updateBedroomResidence|" + + "addKitchen|updateKitchen|removeKitchen|updateKitchenResidence|" + + "addLivingRoom|updateLivingRoom|removeLivingRoom|updateLivingRoomResidence|" + + "addToilet|updateToilet|removeToilet|updateToiletResidence|" + + "addDistrict|updateDistrict|removeDistrict|addToDistrictBuildings|updateDistrictBuildings|removeFromDistrictBuildings|addToDistrictRoads|updateDistrictRoads|removeFromDistrictRoads|" + + "addRoad|updateRoad|removeRoad|" + + "addCyclePath|updateCyclePath|removeCyclePath|" + + "addStaffMember|updateStaffMember|removeStaffMember" + // @formatter:keep_existing_linebreaks restore + )] + public override async Task Expected_names_appear_in_openapi_discriminator_mapping(string schemaName, string? discriminatorValues) + { + await base.Expected_names_appear_in_openapi_discriminator_mapping(schemaName, discriminatorValues); + } + + [Theory] + [InlineData("buildingResourceType", "familyHomes|mansions|residences")] + [InlineData("residenceResourceType", "familyHomes|mansions|residences")] + [InlineData("familyHomeResourceType", null)] + [InlineData("mansionResourceType", "mansions")] + [InlineData("roomResourceType", "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("bathroomResourceType", "bathrooms")] + [InlineData("bedroomResourceType", "bedrooms")] + [InlineData("kitchenResourceType", "kitchens")] + [InlineData("livingRoomResourceType", "livingRooms")] + [InlineData("toiletResourceType", "toilets")] + [InlineData("roadResourceType", "roads|cyclePaths")] + [InlineData("cyclePathResourceType", null)] + [InlineData("districtResourceType", "districts")] + [InlineData("staffMemberResourceType", "staffMembers")] + [InlineData("resourceType", + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|roads|cyclePaths|districts|staffMembers")] + public override async Task Expected_names_appear_in_resource_type_enum(string schemaName, string? enumValues) + { + await base.Expected_names_appear_in_resource_type_enum(schemaName, enumValues); + } + + [Theory] + [InlineData("resourceInCreateRequest", true, null, "type|meta")] + [InlineData("attributesInCreateRequest", true, null, "openapi:discriminator")] + [InlineData("relationshipsInCreateRequest", true, null, "openapi:discriminator")] + [InlineData("resourceInUpdateRequest", true, null, "type|meta")] + [InlineData("attributesInUpdateRequest", true, null, "openapi:discriminator")] + [InlineData("relationshipsInUpdateRequest", true, null, "openapi:discriminator")] + [InlineData("identifierInRequest", true, null, "type|meta")] + [InlineData("resourceInResponse", true, null, "type|meta")] + [InlineData("atomicOperation", true, null, "openapi:discriminator|meta")] + // Building hierarchy: Resource Data + [InlineData("dataInCreateBuildingRequest", true, "resourceInCreateRequest", "lid|attributes|relationships")] + [InlineData("dataInCreateResidenceRequest", false, "dataInCreateBuildingRequest", null)] + [InlineData("dataInCreateFamilyHomeRequest", false, "dataInCreateResidenceRequest", null)] + [InlineData("dataInCreateMansionRequest", false, "dataInCreateResidenceRequest", null)] + [InlineData("dataInUpdateBuildingRequest", true, "resourceInUpdateRequest", "id|lid|attributes|relationships")] + [InlineData("dataInUpdateResidenceRequest", false, "dataInUpdateBuildingRequest", null)] + [InlineData("dataInUpdateFamilyHomeRequest", false, "dataInUpdateResidenceRequest", null)] + [InlineData("dataInUpdateMansionRequest", false, "dataInUpdateResidenceRequest", null)] + [InlineData("dataInBuildingResponse", true, "resourceInResponse", "id|attributes|relationships|links")] + [InlineData("dataInResidenceResponse", false, "dataInBuildingResponse", null)] + [InlineData("dataInFamilyHomeResponse", false, "dataInResidenceResponse", null)] + [InlineData("dataInMansionResponse", false, "dataInResidenceResponse", null)] + // Building hierarchy: Attributes + [InlineData("attributesInCreateBuildingRequest", true, "attributesInCreateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInCreateResidenceRequest", false, "attributesInCreateBuildingRequest", "numberOfResidents")] + [InlineData("attributesInCreateFamilyHomeRequest", false, "attributesInCreateResidenceRequest", "floorCount")] + [InlineData("attributesInCreateMansionRequest", false, "attributesInCreateResidenceRequest", "ownerName")] + [InlineData("attributesInUpdateBuildingRequest", true, "attributesInUpdateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInUpdateResidenceRequest", false, "attributesInUpdateBuildingRequest", "numberOfResidents")] + [InlineData("attributesInUpdateFamilyHomeRequest", false, "attributesInUpdateResidenceRequest", "floorCount")] + [InlineData("attributesInUpdateMansionRequest", false, "attributesInUpdateResidenceRequest", "ownerName")] + [InlineData("attributesInBuildingResponse", true, "attributesInResponse", "surfaceInSquareMeters")] + [InlineData("attributesInResidenceResponse", false, "attributesInBuildingResponse", "numberOfResidents")] + [InlineData("attributesInFamilyHomeResponse", false, "attributesInResidenceResponse", "floorCount")] + [InlineData("attributesInMansionResponse", false, "attributesInResidenceResponse", "ownerName")] + // Building hierarchy: Relationships + [InlineData("relationshipsInCreateBuildingRequest", true, "relationshipsInCreateRequest", null)] + [InlineData("relationshipsInCreateResidenceRequest", false, "relationshipsInCreateBuildingRequest", "rooms")] + [InlineData("relationshipsInCreateFamilyHomeRequest", false, "relationshipsInCreateResidenceRequest", null)] + [InlineData("relationshipsInCreateMansionRequest", false, "relationshipsInCreateResidenceRequest", "staff")] + [InlineData("relationshipsInUpdateBuildingRequest", true, "relationshipsInUpdateRequest", null)] + [InlineData("relationshipsInUpdateResidenceRequest", false, "relationshipsInUpdateBuildingRequest", "rooms")] + [InlineData("relationshipsInUpdateFamilyHomeRequest", false, "relationshipsInUpdateResidenceRequest", null)] + [InlineData("relationshipsInUpdateMansionRequest", false, "relationshipsInUpdateResidenceRequest", "staff")] + [InlineData("relationshipsInBuildingResponse", true, "relationshipsInResponse", null)] + [InlineData("relationshipsInResidenceResponse", false, "relationshipsInBuildingResponse", "rooms")] + [InlineData("relationshipsInFamilyHomeResponse", false, "relationshipsInResidenceResponse", null)] + [InlineData("relationshipsInMansionResponse", false, "relationshipsInResidenceResponse", "staff")] + // Building hierarchy: Resource Identifiers + [InlineData("buildingIdentifierInRequest", false, "identifierInRequest", "id|lid")] + [InlineData("residenceIdentifierInRequest", false, "buildingIdentifierInRequest", null)] + [InlineData("familyHomeIdentifierInRequest", false, "residenceIdentifierInRequest", null)] + [InlineData("mansionIdentifierInRequest", false, "residenceIdentifierInRequest", null)] + [InlineData("buildingIdentifierInResponse", true, null, "type|id|meta")] + [InlineData("residenceIdentifierInResponse", false, "buildingIdentifierInResponse", null)] + [InlineData("familyHomeIdentifierInResponse", false, "residenceIdentifierInResponse", null)] + [InlineData("mansionIdentifierInResponse", false, "residenceIdentifierInResponse", null)] + // Building hierarchy: Atomic Operations + [InlineData("createBuildingOperation", false, null, null)] + [InlineData("createResidenceOperation", false, "atomicOperation", "op|data")] + [InlineData("createFamilyHomeOperation", false, "createResidenceOperation", null)] + [InlineData("createMansionOperation", false, "createResidenceOperation", null)] + [InlineData("updateBuildingOperation", false, null, null)] + [InlineData("updateResidenceOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateFamilyHomeOperation", false, "updateResidenceOperation", null)] + [InlineData("updateMansionOperation", false, "updateResidenceOperation", null)] + [InlineData("deleteBuildingOperation", false, null, null)] + [InlineData("deleteResidenceOperation", false, "atomicOperation", "op|ref")] + [InlineData("deleteFamilyHomeOperation", false, "deleteResidenceOperation", null)] + [InlineData("deleteMansionOperation", false, "deleteResidenceOperation", null)] + [InlineData("updateResidenceRoomsRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateFamilyHomeRoomsRelationshipOperation", false, "updateResidenceRoomsRelationshipOperation", null)] + [InlineData("updateMansionRoomsRelationshipOperation", false, "updateResidenceRoomsRelationshipOperation", null)] + [InlineData("updateMansionStaffRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("addToResidenceRoomsRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("addToFamilyHomeRoomsRelationshipOperation", false, "addToResidenceRoomsRelationshipOperation", null)] + [InlineData("addToMansionRoomsRelationshipOperation", false, "addToResidenceRoomsRelationshipOperation", null)] + [InlineData("addToMansionStaffRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("removeFromResidenceRoomsRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("removeFromFamilyHomeRoomsRelationshipOperation", false, "removeFromResidenceRoomsRelationshipOperation", null)] + [InlineData("removeFromMansionRoomsRelationshipOperation", false, "removeFromResidenceRoomsRelationshipOperation", null)] + [InlineData("removeFromMansionStaffRelationshipOperation", false, "atomicOperation", "op|ref|data")] + // Room hierarchy: Resource Data + [InlineData("dataInCreateRoomRequest", true, "resourceInCreateRequest", "lid|attributes|relationships")] + [InlineData("dataInCreateBathroomRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateBedroomRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateKitchenRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateLivingRoomRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateToiletRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInUpdateRoomRequest", true, "resourceInUpdateRequest", "id|lid|attributes|relationships")] + [InlineData("dataInUpdateBathroomRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInUpdateBedroomRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInUpdateKitchenRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInUpdateLivingRoomRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInUpdateToiletRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInRoomResponse", true, "resourceInResponse", "id|attributes|relationships|links")] + [InlineData("dataInBathroomResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInBedroomResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInKitchenResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInLivingRoomResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInToiletResponse", false, "dataInRoomResponse", null)] + // Room hierarchy: Attributes + [InlineData("attributesInCreateRoomRequest", true, "attributesInCreateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInCreateBathroomRequest", false, "attributesInCreateRoomRequest", "hasBath")] + [InlineData("attributesInCreateBedroomRequest", false, "attributesInCreateRoomRequest", "bedCount")] + [InlineData("attributesInCreateKitchenRequest", false, "attributesInCreateRoomRequest", "hasPantry")] + [InlineData("attributesInCreateLivingRoomRequest", false, "attributesInCreateRoomRequest", "hasDiningTable")] + [InlineData("attributesInCreateToiletRequest", false, "attributesInCreateRoomRequest", "hasSink")] + [InlineData("attributesInUpdateRoomRequest", true, "attributesInUpdateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInUpdateBathroomRequest", false, "attributesInUpdateRoomRequest", "hasBath")] + [InlineData("attributesInUpdateBedroomRequest", false, "attributesInUpdateRoomRequest", "bedCount")] + [InlineData("attributesInUpdateKitchenRequest", false, "attributesInUpdateRoomRequest", "hasPantry")] + [InlineData("attributesInUpdateLivingRoomRequest", false, "attributesInUpdateRoomRequest", "hasDiningTable")] + [InlineData("attributesInUpdateToiletRequest", false, "attributesInUpdateRoomRequest", "hasSink")] + [InlineData("attributesInRoomResponse", true, "attributesInResponse", "surfaceInSquareMeters")] + [InlineData("attributesInBathroomResponse", false, "attributesInRoomResponse", "hasBath")] + [InlineData("attributesInBedroomResponse", false, "attributesInRoomResponse", "bedCount")] + [InlineData("attributesInKitchenResponse", false, "attributesInRoomResponse", "hasPantry")] + [InlineData("attributesInLivingRoomResponse", false, "attributesInRoomResponse", "hasDiningTable")] + [InlineData("attributesInToiletResponse", false, "attributesInRoomResponse", "hasSink")] + // Room hierarchy: Relationships + [InlineData("relationshipsInCreateRoomRequest", true, "relationshipsInCreateRequest", "residence")] + [InlineData("relationshipsInCreateBathroomRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateBedroomRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateKitchenRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateLivingRoomRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateToiletRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInUpdateRoomRequest", true, "relationshipsInUpdateRequest", "residence")] + [InlineData("relationshipsInUpdateBathroomRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInUpdateBedroomRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInUpdateKitchenRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInUpdateLivingRoomRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInUpdateToiletRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInRoomResponse", true, "relationshipsInResponse", "residence")] + [InlineData("relationshipsInBathroomResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInBedroomResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInKitchenResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInLivingRoomResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInToiletResponse", false, "relationshipsInRoomResponse", null)] + // Room hierarchy: Resource Identifiers + [InlineData("roomIdentifierInRequest", false, "identifierInRequest", "id|lid")] + [InlineData("bathroomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("bedroomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("kitchenIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("livingRoomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("toiletIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("roomIdentifierInResponse", true, null, "type|id|meta")] + [InlineData("bathroomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("bedroomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("kitchenIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("livingRoomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("toiletIdentifierInResponse", false, "roomIdentifierInResponse", null)] + // Room hierarchy: Atomic Operations + [InlineData("createRoomOperation", false, null, null)] + [InlineData("createBathroomOperation", false, "atomicOperation", "op|data")] + [InlineData("createBedroomOperation", false, "atomicOperation", "op|data")] + [InlineData("createKitchenOperation", false, "atomicOperation", "op|data")] + [InlineData("createLivingRoomOperation", false, "atomicOperation", "op|data")] + [InlineData("createToiletOperation", false, "atomicOperation", "op|data")] + [InlineData("updateRoomOperation", false, null, null)] + [InlineData("updateBathroomOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateBedroomOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateKitchenOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateLivingRoomOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateToiletOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("deleteRoomOperation", false, null, null)] + [InlineData("deleteBathroomOperation", false, "atomicOperation", "op|ref")] + [InlineData("deleteBedroomOperation", false, "atomicOperation", "op|ref")] + [InlineData("deleteKitchenOperation", false, "atomicOperation", "op|ref")] + [InlineData("deleteLivingRoomOperation", false, "atomicOperation", "op|ref")] + [InlineData("deleteToiletOperation", false, "atomicOperation", "op|ref")] + [InlineData("updateRoomResidenceRelationshipOperation", false, null, null)] + [InlineData("updateBathroomResidenceRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateBedroomResidenceRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateKitchenResidenceRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateLivingRoomResidenceRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateToiletResidenceRelationshipOperation", false, "atomicOperation", "op|ref|data")] + // Road hierarchy: Resource Data + [InlineData("dataInCreateRoadRequest", false, "resourceInCreateRequest", "lid|attributes|relationships")] + [InlineData("dataInCreateCyclePathRequest", false, "dataInCreateRoadRequest", null)] + [InlineData("dataInUpdateRoadRequest", false, "resourceInUpdateRequest", "id|lid|attributes|relationships")] + [InlineData("dataInUpdateCyclePathRequest", false, "dataInUpdateRoadRequest", null)] + [InlineData("dataInRoadResponse", false, "resourceInResponse", "id|attributes|relationships|links")] + [InlineData("dataInCyclePathResponse", false, "dataInRoadResponse", null)] + // Road hierarchy: Attributes + [InlineData("attributesInCreateRoadRequest", false, "attributesInCreateRequest", "lengthInMeters")] + [InlineData("attributesInCreateCyclePathRequest", false, "attributesInCreateRoadRequest", "hasLaneForPedestrians")] + [InlineData("attributesInUpdateRoadRequest", false, "attributesInUpdateRequest", "lengthInMeters")] + [InlineData("attributesInUpdateCyclePathRequest", false, "attributesInUpdateRoadRequest", "hasLaneForPedestrians")] + [InlineData("attributesInRoadResponse", false, "attributesInResponse", "lengthInMeters")] + [InlineData("attributesInCyclePathResponse", false, "attributesInRoadResponse", "hasLaneForPedestrians")] + // Road hierarchy: Relationships + [InlineData("relationshipsInCreateRoadRequest", false, "relationshipsInCreateRequest", null)] + [InlineData("relationshipsInCreateCyclePathRequest", false, "relationshipsInCreateRoadRequest", null)] + [InlineData("relationshipsInUpdateRoadRequest", false, "relationshipsInUpdateRequest", null)] + [InlineData("relationshipsInUpdateCyclePathRequest", false, "relationshipsInUpdateRoadRequest", null)] + [InlineData("relationshipsInRoadResponse", false, "relationshipsInResponse", null)] + [InlineData("relationshipsInCyclePathResponse", false, "relationshipsInRoadResponse", null)] + // Road hierarchy: Resource Identifiers + [InlineData("roadIdentifierInRequest", false, "identifierInRequest", "id|lid")] + [InlineData("cyclePathIdentifierInRequest", false, "roadIdentifierInRequest", null)] + [InlineData("roadIdentifierInResponse", false, null, "type|id|meta")] + [InlineData("cyclePathIdentifierInResponse", false, "roadIdentifierInResponse", null)] + // Road hierarchy: Atomic Operations + [InlineData("createRoadOperation", false, "atomicOperation", "op|data")] + [InlineData("createCyclePathOperation", false, "createRoadOperation", null)] + [InlineData("updateRoadOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateCyclePathOperation", false, "updateRoadOperation", null)] + [InlineData("deleteRoadOperation", false, "atomicOperation", "op|ref")] + [InlineData("deleteCyclePathOperation", false, "deleteRoadOperation", null)] + public override async Task Component_schemas_have_expected_base_type(string schemaName, bool isAbstract, string? baseType, string? properties) + { + await base.Component_schemas_have_expected_base_type(schemaName, isAbstract, baseType, properties); + } +} diff --git a/test/OpenApiTests/ResourceInheritance/OnlyConcrete/OnlyConcreteOperationFilter.cs b/test/OpenApiTests/ResourceInheritance/OnlyConcrete/OnlyConcreteOperationFilter.cs new file mode 100644 index 0000000000..c29b005b5f --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/OnlyConcrete/OnlyConcreteOperationFilter.cs @@ -0,0 +1,13 @@ +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; + +namespace OpenApiTests.ResourceInheritance.OnlyConcrete; + +public sealed class OnlyConcreteOperationFilter : DefaultOperationFilter +{ + protected override JsonApiEndpoints? GetJsonApiEndpoints(ResourceType resourceType) + { + return resourceType.ClrType.IsAbstract ? JsonApiEndpoints.None : JsonApiEndpoints.All; + } +} diff --git a/test/OpenApiTests/ResourceInheritance/OnlyOperations/OnlyOperationsEndpointFilter.cs b/test/OpenApiTests/ResourceInheritance/OnlyOperations/OnlyOperationsEndpointFilter.cs new file mode 100644 index 0000000000..2306a52b98 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/OnlyOperations/OnlyOperationsEndpointFilter.cs @@ -0,0 +1,13 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; + +namespace OpenApiTests.ResourceInheritance.OnlyOperations; + +public sealed class OnlyOperationsEndpointFilter : IJsonApiEndpointFilter +{ + public bool IsEnabled(ResourceType resourceType, JsonApiEndpoints endpoint) + { + return false; + } +} diff --git a/test/OpenApiTests/ResourceInheritance/OnlyOperations/OnlyOperationsInheritanceTests.cs b/test/OpenApiTests/ResourceInheritance/OnlyOperations/OnlyOperationsInheritanceTests.cs new file mode 100644 index 0000000000..94ada069cc --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/OnlyOperations/OnlyOperationsInheritanceTests.cs @@ -0,0 +1,350 @@ +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; +using Microsoft.Extensions.DependencyInjection; +using OpenApiTests.ResourceInheritance.Models; +using Xunit; +using Xunit.Abstractions; + +#pragma warning disable format + +namespace OpenApiTests.ResourceInheritance.OnlyOperations; + +public sealed class OnlyOperationsInheritanceTests : ResourceInheritanceTests +{ + public OnlyOperationsInheritanceTests(OpenApiTestContext, ResourceInheritanceDbContext> testContext, + ITestOutputHelper testOutputHelper) + : base(testContext, testOutputHelper, true, false) + { + testContext.ConfigureServices(services => + { + services.AddSingleton(); + services.AddSingleton(); + }); + } + + [Theory] + [InlineData(typeof(District), JsonApiEndpoints.None)] + [InlineData(typeof(StaffMember), JsonApiEndpoints.None)] + [InlineData(typeof(Building), JsonApiEndpoints.None)] + [InlineData(typeof(Residence), JsonApiEndpoints.None)] + [InlineData(typeof(FamilyHome), JsonApiEndpoints.None)] + [InlineData(typeof(Mansion), JsonApiEndpoints.None)] + [InlineData(typeof(Room), JsonApiEndpoints.None)] + [InlineData(typeof(Kitchen), JsonApiEndpoints.None)] + [InlineData(typeof(Bedroom), JsonApiEndpoints.None)] + [InlineData(typeof(Bathroom), JsonApiEndpoints.None)] + [InlineData(typeof(LivingRoom), JsonApiEndpoints.None)] + [InlineData(typeof(Toilet), JsonApiEndpoints.None)] + [InlineData(typeof(Road), JsonApiEndpoints.None)] + [InlineData(typeof(CyclePath), JsonApiEndpoints.None)] + public override async Task Only_expected_endpoints_are_exposed(Type resourceClrType, JsonApiEndpoints expected) + { + await base.Only_expected_endpoints_are_exposed(resourceClrType, expected); + } + + [Theory] + [InlineData(true)] + public override async Task Operations_endpoint_is_exposed(bool enabled) + { + await base.Operations_endpoint_is_exposed(enabled); + } + + [Theory] + [InlineData("resourceInCreateRequest", false, + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|districts|roads|cyclePaths|staffMembers")] + [InlineData("resourceInUpdateRequest", false, + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|districts|roads|cyclePaths|staffMembers")] + [InlineData("identifierInRequest", false, + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|districts|roads|cyclePaths|staffMembers")] + [InlineData("resourceInResponse", false, + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|districts|roads|cyclePaths|staffMembers")] + [InlineData("dataInBuildingResponse", true, "familyHomes|mansions|residences")] + [InlineData("buildingIdentifierInResponse", false, "familyHomes|mansions|residences")] + [InlineData("dataInResidenceResponse", true, "familyHomes|mansions")] + [InlineData("residenceIdentifierInResponse", true, "familyHomes|mansions")] + [InlineData("dataInRoomResponse", true, "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("roomIdentifierInResponse", false, "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("dataInRoadResponse", true, "cyclePaths")] + [InlineData("roadIdentifierInResponse", false, "cyclePaths")] + public override async Task Expected_names_appear_in_type_discriminator_mapping(string schemaName, bool isWrapped, string? discriminatorValues) + { + await base.Expected_names_appear_in_type_discriminator_mapping(schemaName, isWrapped, discriminatorValues); + } + + [Theory] + [InlineData("attributesInCreateRequest", + "familyHomes|mansions|residences|buildings|bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|cyclePaths|roads|districts|staffMembers")] + [InlineData("attributesInUpdateRequest", + "familyHomes|mansions|residences|buildings|bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|cyclePaths|roads|districts|staffMembers")] + [InlineData("relationshipsInCreateRequest", + "familyHomes|mansions|residences|buildings|bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|cyclePaths|roads|districts")] + [InlineData("relationshipsInUpdateRequest", + "familyHomes|mansions|residences|buildings|bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|cyclePaths|roads|districts")] + [InlineData("!attributesInBuildingResponse", "familyHomes|mansions|residences")] + [InlineData("!relationshipsInBuildingResponse", "familyHomes|mansions|residences")] + [InlineData("!attributesInRoomResponse", "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("!relationshipsInRoomResponse", "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("!attributesInRoadResponse", "cyclePaths")] + [InlineData("!relationshipsInRoadResponse", "cyclePaths")] + [InlineData("atomicOperation", + // @formatter:keep_existing_linebreaks true + "addBuilding|updateBuilding|removeBuilding|" + + "addResidence|updateResidence|removeResidence|addToResidenceRooms|updateResidenceRooms|removeFromResidenceRooms|" + + "addFamilyHome|updateFamilyHome|removeFamilyHome|addToFamilyHomeRooms|updateFamilyHomeRooms|removeFromFamilyHomeRooms|" + + "addMansion|updateMansion|removeMansion|addToMansionRooms|updateMansionRooms|removeFromMansionRooms|addToMansionStaff|updateMansionStaff|removeFromMansionStaff|" + + "addRoom|updateRoom|removeRoom|updateRoomResidence|" + + "addBathroom|updateBathroom|removeBathroom|updateBathroomResidence|" + + "addBedroom|updateBedroom|removeBedroom|updateBedroomResidence|" + + "addKitchen|updateKitchen|removeKitchen|updateKitchenResidence|" + + "addLivingRoom|updateLivingRoom|removeLivingRoom|updateLivingRoomResidence|" + + "addToilet|updateToilet|removeToilet|updateToiletResidence|" + + "addDistrict|updateDistrict|removeDistrict|addToDistrictBuildings|updateDistrictBuildings|removeFromDistrictBuildings|addToDistrictRoads|updateDistrictRoads|removeFromDistrictRoads|" + + "addRoad|updateRoad|removeRoad|" + + "addCyclePath|updateCyclePath|removeCyclePath|" + + "addStaffMember|updateStaffMember|removeStaffMember" + // @formatter:keep_existing_linebreaks restore + )] + public override async Task Expected_names_appear_in_openapi_discriminator_mapping(string schemaName, string? discriminatorValues) + { + await base.Expected_names_appear_in_openapi_discriminator_mapping(schemaName, discriminatorValues); + } + + [Theory] + [InlineData("buildingResourceType", "familyHomes|mansions|residences")] + [InlineData("residenceResourceType", "familyHomes|mansions|residences")] + [InlineData("familyHomeResourceType", null)] + [InlineData("mansionResourceType", "mansions")] + [InlineData("roomResourceType", "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("bathroomResourceType", null)] + [InlineData("bedroomResourceType", null)] + [InlineData("kitchenResourceType", null)] + [InlineData("livingRoomResourceType", null)] + [InlineData("toiletResourceType", null)] + [InlineData("roadResourceType", "roads|cyclePaths")] + [InlineData("cyclePathResourceType", null)] + [InlineData("districtResourceType", "districts")] + [InlineData("staffMemberResourceType", "staffMembers")] + [InlineData("resourceType", + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|roads|cyclePaths|districts|staffMembers")] + public override async Task Expected_names_appear_in_resource_type_enum(string schemaName, string? enumValues) + { + await base.Expected_names_appear_in_resource_type_enum(schemaName, enumValues); + } + + [Theory] + [InlineData("resourceInCreateRequest", true, null, "type|meta")] + [InlineData("attributesInCreateRequest", true, null, "openapi:discriminator")] + [InlineData("relationshipsInCreateRequest", true, null, "openapi:discriminator")] + [InlineData("resourceInUpdateRequest", true, null, "type|meta")] + [InlineData("attributesInUpdateRequest", true, null, "openapi:discriminator")] + [InlineData("relationshipsInUpdateRequest", true, null, "openapi:discriminator")] + [InlineData("identifierInRequest", true, null, "type|meta")] + [InlineData("resourceInResponse", true, null, "type|meta")] + [InlineData("atomicOperation", true, null, "openapi:discriminator|meta")] + // Building hierarchy: Resource Data + [InlineData("dataInCreateBuildingRequest", true, "resourceInCreateRequest", "lid|attributes|relationships")] + [InlineData("dataInCreateResidenceRequest", false, "dataInCreateBuildingRequest", null)] + [InlineData("dataInCreateFamilyHomeRequest", false, "dataInCreateResidenceRequest", null)] + [InlineData("dataInCreateMansionRequest", false, "dataInCreateResidenceRequest", null)] + [InlineData("dataInUpdateBuildingRequest", true, "resourceInUpdateRequest", "id|lid|attributes|relationships")] + [InlineData("dataInUpdateResidenceRequest", false, "dataInUpdateBuildingRequest", null)] + [InlineData("dataInUpdateFamilyHomeRequest", false, "dataInUpdateResidenceRequest", null)] + [InlineData("dataInUpdateMansionRequest", false, "dataInUpdateResidenceRequest", null)] + [InlineData("dataInBuildingResponse", true, "resourceInResponse", "id|attributes|relationships|links")] + [InlineData("dataInResidenceResponse", false, "dataInBuildingResponse", null)] + [InlineData("dataInFamilyHomeResponse", false, "dataInResidenceResponse", null)] + [InlineData("dataInMansionResponse", false, "dataInResidenceResponse", null)] + // Building hierarchy: Attributes + [InlineData("attributesInCreateBuildingRequest", true, "attributesInCreateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInCreateResidenceRequest", false, "attributesInCreateBuildingRequest", "numberOfResidents")] + [InlineData("attributesInCreateFamilyHomeRequest", false, "attributesInCreateResidenceRequest", "floorCount")] + [InlineData("attributesInCreateMansionRequest", false, "attributesInCreateResidenceRequest", "ownerName")] + [InlineData("attributesInUpdateBuildingRequest", true, "attributesInUpdateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInUpdateResidenceRequest", false, "attributesInUpdateBuildingRequest", "numberOfResidents")] + [InlineData("attributesInUpdateFamilyHomeRequest", false, "attributesInUpdateResidenceRequest", "floorCount")] + [InlineData("attributesInUpdateMansionRequest", false, "attributesInUpdateResidenceRequest", "ownerName")] + [InlineData("attributesInBuildingResponse", true, "attributesInResponse", "surfaceInSquareMeters")] + [InlineData("attributesInResidenceResponse", false, "attributesInBuildingResponse", "numberOfResidents")] + [InlineData("attributesInFamilyHomeResponse", false, "attributesInResidenceResponse", "floorCount")] + [InlineData("attributesInMansionResponse", false, "attributesInResidenceResponse", "ownerName")] + // Building hierarchy: Relationships + [InlineData("relationshipsInCreateBuildingRequest", true, "relationshipsInCreateRequest", null)] + [InlineData("relationshipsInCreateResidenceRequest", false, "relationshipsInCreateBuildingRequest", "rooms")] + [InlineData("relationshipsInCreateFamilyHomeRequest", false, "relationshipsInCreateResidenceRequest", null)] + [InlineData("relationshipsInCreateMansionRequest", false, "relationshipsInCreateResidenceRequest", "staff")] + [InlineData("relationshipsInUpdateBuildingRequest", true, "relationshipsInUpdateRequest", null)] + [InlineData("relationshipsInUpdateResidenceRequest", false, "relationshipsInUpdateBuildingRequest", "rooms")] + [InlineData("relationshipsInUpdateFamilyHomeRequest", false, "relationshipsInUpdateResidenceRequest", null)] + [InlineData("relationshipsInUpdateMansionRequest", false, "relationshipsInUpdateResidenceRequest", "staff")] + [InlineData("relationshipsInBuildingResponse", true, "relationshipsInResponse", null)] + [InlineData("relationshipsInResidenceResponse", false, "relationshipsInBuildingResponse", "rooms")] + [InlineData("relationshipsInFamilyHomeResponse", false, "relationshipsInResidenceResponse", null)] + [InlineData("relationshipsInMansionResponse", false, "relationshipsInResidenceResponse", "staff")] + // Building hierarchy: Resource Identifiers + [InlineData("buildingIdentifierInRequest", false, "identifierInRequest", "id|lid")] + [InlineData("residenceIdentifierInRequest", false, "buildingIdentifierInRequest", null)] + [InlineData("familyHomeIdentifierInRequest", false, "residenceIdentifierInRequest", null)] + [InlineData("mansionIdentifierInRequest", false, "residenceIdentifierInRequest", null)] + [InlineData("buildingIdentifierInResponse", true, null, "type|id|meta")] + [InlineData("residenceIdentifierInResponse", false, "buildingIdentifierInResponse", null)] + [InlineData("familyHomeIdentifierInResponse", false, "residenceIdentifierInResponse", null)] + [InlineData("mansionIdentifierInResponse", false, "residenceIdentifierInResponse", null)] + // Building hierarchy: Atomic Operations + [InlineData("createBuildingOperation", false, "atomicOperation", "op|data")] + [InlineData("createResidenceOperation", false, "createBuildingOperation", null)] + [InlineData("createFamilyHomeOperation", false, "createResidenceOperation", null)] + [InlineData("createMansionOperation", false, "createResidenceOperation", null)] + [InlineData("updateBuildingOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateResidenceOperation", false, "updateBuildingOperation", null)] + [InlineData("updateFamilyHomeOperation", false, "updateResidenceOperation", null)] + [InlineData("updateMansionOperation", false, "updateResidenceOperation", null)] + [InlineData("deleteBuildingOperation", false, "atomicOperation", "op|ref")] + [InlineData("deleteResidenceOperation", false, "deleteBuildingOperation", null)] + [InlineData("deleteFamilyHomeOperation", false, "deleteResidenceOperation", null)] + [InlineData("deleteMansionOperation", false, "deleteResidenceOperation", null)] + [InlineData("updateResidenceRoomsRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateFamilyHomeRoomsRelationshipOperation", false, "updateResidenceRoomsRelationshipOperation", null)] + [InlineData("updateMansionRoomsRelationshipOperation", false, "updateResidenceRoomsRelationshipOperation", null)] + [InlineData("updateMansionStaffRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("addToResidenceRoomsRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("addToFamilyHomeRoomsRelationshipOperation", false, "addToResidenceRoomsRelationshipOperation", null)] + [InlineData("addToMansionRoomsRelationshipOperation", false, "addToResidenceRoomsRelationshipOperation", null)] + [InlineData("addToMansionStaffRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("removeFromResidenceRoomsRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("removeFromFamilyHomeRoomsRelationshipOperation", false, "removeFromResidenceRoomsRelationshipOperation", null)] + [InlineData("removeFromMansionRoomsRelationshipOperation", false, "removeFromResidenceRoomsRelationshipOperation", null)] + [InlineData("removeFromMansionStaffRelationshipOperation", false, "atomicOperation", "op|ref|data")] + // Room hierarchy: Resource Data + [InlineData("dataInCreateRoomRequest", true, "resourceInCreateRequest", "lid|attributes|relationships")] + [InlineData("dataInCreateBathroomRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateBedroomRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateKitchenRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateLivingRoomRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateToiletRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInUpdateRoomRequest", true, "resourceInUpdateRequest", "id|lid|attributes|relationships")] + [InlineData("dataInUpdateBathroomRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInUpdateBedroomRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInUpdateKitchenRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInUpdateLivingRoomRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInUpdateToiletRequest", false, "dataInUpdateRoomRequest", null)] + [InlineData("dataInRoomResponse", true, "resourceInResponse", "id|attributes|relationships|links")] + [InlineData("dataInBathroomResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInBedroomResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInKitchenResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInLivingRoomResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInToiletResponse", false, "dataInRoomResponse", null)] + // Room hierarchy: Attributes + [InlineData("attributesInCreateRoomRequest", true, "attributesInCreateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInCreateBathroomRequest", false, "attributesInCreateRoomRequest", "hasBath")] + [InlineData("attributesInCreateBedroomRequest", false, "attributesInCreateRoomRequest", "bedCount")] + [InlineData("attributesInCreateKitchenRequest", false, "attributesInCreateRoomRequest", "hasPantry")] + [InlineData("attributesInCreateLivingRoomRequest", false, "attributesInCreateRoomRequest", "hasDiningTable")] + [InlineData("attributesInCreateToiletRequest", false, "attributesInCreateRoomRequest", "hasSink")] + [InlineData("attributesInUpdateRoomRequest", true, "attributesInUpdateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInUpdateBathroomRequest", false, "attributesInUpdateRoomRequest", "hasBath")] + [InlineData("attributesInUpdateBedroomRequest", false, "attributesInUpdateRoomRequest", "bedCount")] + [InlineData("attributesInUpdateKitchenRequest", false, "attributesInUpdateRoomRequest", "hasPantry")] + [InlineData("attributesInUpdateLivingRoomRequest", false, "attributesInUpdateRoomRequest", "hasDiningTable")] + [InlineData("attributesInUpdateToiletRequest", false, "attributesInUpdateRoomRequest", "hasSink")] + [InlineData("attributesInRoomResponse", true, "attributesInResponse", "surfaceInSquareMeters")] + [InlineData("attributesInBathroomResponse", false, "attributesInRoomResponse", "hasBath")] + [InlineData("attributesInBedroomResponse", false, "attributesInRoomResponse", "bedCount")] + [InlineData("attributesInKitchenResponse", false, "attributesInRoomResponse", "hasPantry")] + [InlineData("attributesInLivingRoomResponse", false, "attributesInRoomResponse", "hasDiningTable")] + [InlineData("attributesInToiletResponse", false, "attributesInRoomResponse", "hasSink")] + // Room hierarchy: Relationships + [InlineData("relationshipsInCreateRoomRequest", true, "relationshipsInCreateRequest", "residence")] + [InlineData("relationshipsInCreateBathroomRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateBedroomRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateKitchenRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateLivingRoomRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateToiletRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInUpdateRoomRequest", true, "relationshipsInUpdateRequest", "residence")] + [InlineData("relationshipsInUpdateBathroomRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInUpdateBedroomRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInUpdateKitchenRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInUpdateLivingRoomRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInUpdateToiletRequest", false, "relationshipsInUpdateRoomRequest", null)] + [InlineData("relationshipsInRoomResponse", true, "relationshipsInResponse", "residence")] + [InlineData("relationshipsInBathroomResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInBedroomResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInKitchenResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInLivingRoomResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInToiletResponse", false, "relationshipsInRoomResponse", null)] + // Room hierarchy: Resource Identifiers + [InlineData("roomIdentifierInRequest", false, "identifierInRequest", "id|lid")] + [InlineData("bathroomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("bedroomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("kitchenIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("livingRoomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("toiletIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("roomIdentifierInResponse", true, null, "type|id|meta")] + [InlineData("bathroomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("bedroomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("kitchenIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("livingRoomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("toiletIdentifierInResponse", false, "roomIdentifierInResponse", null)] + // Room hierarchy: Atomic Operations + [InlineData("createRoomOperation", false, "atomicOperation", "op|data")] + [InlineData("createBathroomOperation", false, "createRoomOperation", null)] + [InlineData("createBedroomOperation", false, "createRoomOperation", null)] + [InlineData("createKitchenOperation", false, "createRoomOperation", null)] + [InlineData("createLivingRoomOperation", false, "createRoomOperation", null)] + [InlineData("createToiletOperation", false, "createRoomOperation", null)] + [InlineData("updateRoomOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateBathroomOperation", false, "updateRoomOperation", null)] + [InlineData("updateBedroomOperation", false, "updateRoomOperation", null)] + [InlineData("updateKitchenOperation", false, "updateRoomOperation", null)] + [InlineData("updateLivingRoomOperation", false, "updateRoomOperation", null)] + [InlineData("updateToiletOperation", false, "updateRoomOperation", null)] + [InlineData("deleteRoomOperation", false, "atomicOperation", "op|ref")] + [InlineData("deleteBathroomOperation", false, "deleteRoomOperation", null)] + [InlineData("deleteBedroomOperation", false, "deleteRoomOperation", null)] + [InlineData("deleteKitchenOperation", false, "deleteRoomOperation", null)] + [InlineData("deleteLivingRoomOperation", false, "deleteRoomOperation", null)] + [InlineData("deleteToiletOperation", false, "deleteRoomOperation", null)] + [InlineData("updateRoomResidenceRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateBathroomResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + [InlineData("updateBedroomResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + [InlineData("updateKitchenResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + [InlineData("updateLivingRoomResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + [InlineData("updateToiletResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + // Road hierarchy: Resource Data + [InlineData("dataInCreateRoadRequest", false, "resourceInCreateRequest", "lid|attributes|relationships")] + [InlineData("dataInCreateCyclePathRequest", false, "dataInCreateRoadRequest", null)] + [InlineData("dataInUpdateRoadRequest", false, "resourceInUpdateRequest", "id|lid|attributes|relationships")] + [InlineData("dataInUpdateCyclePathRequest", false, "dataInUpdateRoadRequest", null)] + [InlineData("dataInRoadResponse", false, "resourceInResponse", "id|attributes|relationships|links")] + [InlineData("dataInCyclePathResponse", false, "dataInRoadResponse", null)] + // Road hierarchy: Attributes + [InlineData("attributesInCreateRoadRequest", false, "attributesInCreateRequest", "lengthInMeters")] + [InlineData("attributesInCreateCyclePathRequest", false, "attributesInCreateRoadRequest", "hasLaneForPedestrians")] + [InlineData("attributesInUpdateRoadRequest", false, "attributesInUpdateRequest", "lengthInMeters")] + [InlineData("attributesInUpdateCyclePathRequest", false, "attributesInUpdateRoadRequest", "hasLaneForPedestrians")] + [InlineData("attributesInRoadResponse", false, "attributesInResponse", "lengthInMeters")] + [InlineData("attributesInCyclePathResponse", false, "attributesInRoadResponse", "hasLaneForPedestrians")] + // Road hierarchy: Relationships + [InlineData("relationshipsInCreateRoadRequest", false, "relationshipsInCreateRequest", null)] + [InlineData("relationshipsInCreateCyclePathRequest", false, "relationshipsInCreateRoadRequest", null)] + [InlineData("relationshipsInUpdateRoadRequest", false, "relationshipsInUpdateRequest", null)] + [InlineData("relationshipsInUpdateCyclePathRequest", false, "relationshipsInUpdateRoadRequest", null)] + [InlineData("relationshipsInRoadResponse", false, "relationshipsInResponse", null)] + [InlineData("relationshipsInCyclePathResponse", false, "relationshipsInRoadResponse", null)] + // Road hierarchy: Resource Identifiers + [InlineData("roadIdentifierInRequest", false, "identifierInRequest", "id|lid")] + [InlineData("cyclePathIdentifierInRequest", false, "roadIdentifierInRequest", null)] + [InlineData("roadIdentifierInResponse", false, null, "type|id|meta")] + [InlineData("cyclePathIdentifierInResponse", false, "roadIdentifierInResponse", null)] + // Road hierarchy: Atomic Operations + [InlineData("createRoadOperation", false, "atomicOperation", "op|data")] + [InlineData("createCyclePathOperation", false, "createRoadOperation", null)] + [InlineData("updateRoadOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateCyclePathOperation", false, "updateRoadOperation", null)] + [InlineData("deleteRoadOperation", false, "atomicOperation", "op|ref")] + [InlineData("deleteCyclePathOperation", false, "deleteRoadOperation", null)] + public override async Task Component_schemas_have_expected_base_type(string schemaName, bool isAbstract, string? baseType, string? properties) + { + await base.Component_schemas_have_expected_base_type(schemaName, isAbstract, baseType, properties); + } +} diff --git a/test/OpenApiTests/ResourceInheritance/OnlyOperations/OnlyOperationsOperationFilter.cs b/test/OpenApiTests/ResourceInheritance/OnlyOperations/OnlyOperationsOperationFilter.cs new file mode 100644 index 0000000000..d919512f97 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/OnlyOperations/OnlyOperationsOperationFilter.cs @@ -0,0 +1,13 @@ +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; + +namespace OpenApiTests.ResourceInheritance.OnlyOperations; + +public sealed class OnlyOperationsOperationFilter : DefaultOperationFilter +{ + protected override JsonApiEndpoints? GetJsonApiEndpoints(ResourceType resourceType) + { + return JsonApiEndpoints.All; + } +} diff --git a/test/OpenApiTests/ResourceInheritance/OnlyRelationships/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/ResourceInheritance/OnlyRelationships/GeneratedSwagger/swagger.g.json new file mode 100644 index 0000000000..c9cdbea0b0 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/OnlyRelationships/GeneratedSwagger/swagger.g.json @@ -0,0 +1,6194 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "OpenApiTests", + "version": "1.0" + }, + "servers": [ + { + "url": "http://localhost" + } + ], + "paths": { + "/bathrooms/{id}/relationships/residence": { + "get": { + "tags": [ + "bathrooms" + ], + "summary": "Retrieves the related residence identity of an individual bathroom's residence relationship.", + "operationId": "getBathroomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bathroom whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found residence identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/residenceIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The bathroom does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "bathrooms" + ], + "summary": "Retrieves the related residence identity of an individual bathroom's residence relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headBathroomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bathroom whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The bathroom does not exist." + } + } + }, + "patch": { + "tags": [ + "bathrooms" + ], + "summary": "Assigns an existing residence to the residence relationship of an individual bathroom.", + "operationId": "patchBathroomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bathroom whose residence relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identity of the residence to assign to the residence relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneResidenceInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The residence relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The bathroom or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/bedrooms/{id}/relationships/residence": { + "get": { + "tags": [ + "bedrooms" + ], + "summary": "Retrieves the related residence identity of an individual bedroom's residence relationship.", + "operationId": "getBedroomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bedroom whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found residence identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/residenceIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The bedroom does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "bedrooms" + ], + "summary": "Retrieves the related residence identity of an individual bedroom's residence relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headBedroomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bedroom whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The bedroom does not exist." + } + } + }, + "patch": { + "tags": [ + "bedrooms" + ], + "summary": "Assigns an existing residence to the residence relationship of an individual bedroom.", + "operationId": "patchBedroomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the bedroom whose residence relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identity of the residence to assign to the residence relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneResidenceInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The residence relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The bedroom or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/districts/{id}/relationships/buildings": { + "get": { + "tags": [ + "districts" + ], + "summary": "Retrieves the related building identities of an individual district's buildings relationship.", + "operationId": "getDistrictBuildingsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district whose related building identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found building identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/buildingIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The district does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "districts" + ], + "summary": "Retrieves the related building identities of an individual district's buildings relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headDistrictBuildingsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district whose related building identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The district does not exist." + } + } + }, + "post": { + "tags": [ + "districts" + ], + "summary": "Adds existing buildings to the buildings relationship of an individual district.", + "operationId": "postDistrictBuildingsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district to add buildings to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "description": "The identities of the buildings to add to the buildings relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyBuildingInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The buildings were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The district or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "districts" + ], + "summary": "Assigns existing buildings to the buildings relationship of an individual district.", + "operationId": "patchDistrictBuildingsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district whose buildings relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "description": "The identities of the buildings to assign to the buildings relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyBuildingInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The buildings relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The district or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "districts" + ], + "summary": "Removes existing buildings from the buildings relationship of an individual district.", + "operationId": "deleteDistrictBuildingsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district to remove buildings from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "description": "The identities of the buildings to remove from the buildings relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyBuildingInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The buildings were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The district or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/districts/{id}/relationships/roads": { + "get": { + "tags": [ + "districts" + ], + "summary": "Retrieves the related road identities of an individual district's roads relationship.", + "operationId": "getDistrictRoadsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district whose related road identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found road identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/roadIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The district does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "districts" + ], + "summary": "Retrieves the related road identities of an individual district's roads relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headDistrictRoadsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district whose related road identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The district does not exist." + } + } + }, + "post": { + "tags": [ + "districts" + ], + "summary": "Adds existing roads to the roads relationship of an individual district.", + "operationId": "postDistrictRoadsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district to add roads to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "description": "The identities of the roads to add to the roads relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoadInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The roads were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The district or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "districts" + ], + "summary": "Assigns existing roads to the roads relationship of an individual district.", + "operationId": "patchDistrictRoadsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district whose roads relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "description": "The identities of the roads to assign to the roads relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoadInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The roads relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The district or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "districts" + ], + "summary": "Removes existing roads from the roads relationship of an individual district.", + "operationId": "deleteDistrictRoadsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the district to remove roads from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "description": "The identities of the roads to remove from the roads relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoadInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The roads were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The district or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/familyHomes/{id}/relationships/rooms": { + "get": { + "tags": [ + "familyHomes" + ], + "summary": "Retrieves the related room identities of an individual familyHome's rooms relationship.", + "operationId": "getFamilyHomeRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the familyHome whose related room identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found room identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/roomIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The familyHome does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "familyHomes" + ], + "summary": "Retrieves the related room identities of an individual familyHome's rooms relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headFamilyHomeRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the familyHome whose related room identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The familyHome does not exist." + } + } + }, + "post": { + "tags": [ + "familyHomes" + ], + "summary": "Adds existing rooms to the rooms relationship of an individual familyHome.", + "operationId": "postFamilyHomeRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the familyHome to add rooms to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the rooms to add to the rooms relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The rooms were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The familyHome or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "familyHomes" + ], + "summary": "Assigns existing rooms to the rooms relationship of an individual familyHome.", + "operationId": "patchFamilyHomeRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the familyHome whose rooms relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the rooms to assign to the rooms relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The rooms relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The familyHome or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "familyHomes" + ], + "summary": "Removes existing rooms from the rooms relationship of an individual familyHome.", + "operationId": "deleteFamilyHomeRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the familyHome to remove rooms from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the rooms to remove from the rooms relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The rooms were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The familyHome or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/kitchens/{id}/relationships/residence": { + "get": { + "tags": [ + "kitchens" + ], + "summary": "Retrieves the related residence identity of an individual kitchen's residence relationship.", + "operationId": "getKitchenResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the kitchen whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found residence identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/residenceIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The kitchen does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "kitchens" + ], + "summary": "Retrieves the related residence identity of an individual kitchen's residence relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headKitchenResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the kitchen whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The kitchen does not exist." + } + } + }, + "patch": { + "tags": [ + "kitchens" + ], + "summary": "Assigns an existing residence to the residence relationship of an individual kitchen.", + "operationId": "patchKitchenResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the kitchen whose residence relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identity of the residence to assign to the residence relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneResidenceInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The residence relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The kitchen or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/livingRooms/{id}/relationships/residence": { + "get": { + "tags": [ + "livingRooms" + ], + "summary": "Retrieves the related residence identity of an individual livingRoom's residence relationship.", + "operationId": "getLivingRoomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the livingRoom whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found residence identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/residenceIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The livingRoom does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "livingRooms" + ], + "summary": "Retrieves the related residence identity of an individual livingRoom's residence relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headLivingRoomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the livingRoom whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The livingRoom does not exist." + } + } + }, + "patch": { + "tags": [ + "livingRooms" + ], + "summary": "Assigns an existing residence to the residence relationship of an individual livingRoom.", + "operationId": "patchLivingRoomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the livingRoom whose residence relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identity of the residence to assign to the residence relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneResidenceInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The residence relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The livingRoom or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/mansions/{id}/relationships/rooms": { + "get": { + "tags": [ + "mansions" + ], + "summary": "Retrieves the related room identities of an individual mansion's rooms relationship.", + "operationId": "getMansionRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion whose related room identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found room identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/roomIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The mansion does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "mansions" + ], + "summary": "Retrieves the related room identities of an individual mansion's rooms relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headMansionRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion whose related room identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The mansion does not exist." + } + } + }, + "post": { + "tags": [ + "mansions" + ], + "summary": "Adds existing rooms to the rooms relationship of an individual mansion.", + "operationId": "postMansionRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion to add rooms to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the rooms to add to the rooms relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The rooms were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The mansion or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "mansions" + ], + "summary": "Assigns existing rooms to the rooms relationship of an individual mansion.", + "operationId": "patchMansionRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion whose rooms relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the rooms to assign to the rooms relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The rooms relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The mansion or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "mansions" + ], + "summary": "Removes existing rooms from the rooms relationship of an individual mansion.", + "operationId": "deleteMansionRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion to remove rooms from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the rooms to remove from the rooms relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The rooms were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The mansion or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/mansions/{id}/relationships/staff": { + "get": { + "tags": [ + "mansions" + ], + "summary": "Retrieves the related staffMember identities of an individual mansion's staff relationship.", + "operationId": "getMansionStaffRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion whose related staffMember identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found staffMember identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/staffMemberIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The mansion does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "mansions" + ], + "summary": "Retrieves the related staffMember identities of an individual mansion's staff relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headMansionStaffRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion whose related staffMember identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The mansion does not exist." + } + } + }, + "post": { + "tags": [ + "mansions" + ], + "summary": "Adds existing staffMembers to the staff relationship of an individual mansion.", + "operationId": "postMansionStaffRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion to add staffMembers to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the staffMembers to add to the staff relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStaffMemberInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The staffMembers were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The mansion or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "mansions" + ], + "summary": "Assigns existing staffMembers to the staff relationship of an individual mansion.", + "operationId": "patchMansionStaffRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion whose staff relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the staffMembers to assign to the staff relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStaffMemberInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The staff relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The mansion or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "mansions" + ], + "summary": "Removes existing staffMembers from the staff relationship of an individual mansion.", + "operationId": "deleteMansionStaffRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the mansion to remove staffMembers from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the staffMembers to remove from the staff relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStaffMemberInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The staffMembers were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The mansion or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/operations": { + "post": { + "tags": [ + "operations" + ], + "summary": "Performs multiple mutations in a linear and atomic manner.", + "operationId": "postOperations", + "requestBody": { + "description": "An array of mutation operations. For syntax, see the [Atomic Operations documentation](https://jsonapi.org/ext/atomic/).", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/operationsRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "All operations were successfully applied, which resulted in additional changes.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/operationsResponseDocument" + } + } + } + }, + "204": { + "description": "All operations were successfully applied, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "An operation is not accessible or a client-generated ID is used.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/residences/{id}/relationships/rooms": { + "get": { + "tags": [ + "residences" + ], + "summary": "Retrieves the related room identities of an individual residence's rooms relationship.", + "operationId": "getResidenceRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the residence whose related room identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found room identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/roomIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The residence does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "residences" + ], + "summary": "Retrieves the related room identities of an individual residence's rooms relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headResidenceRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the residence whose related room identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The residence does not exist." + } + } + }, + "post": { + "tags": [ + "residences" + ], + "summary": "Adds existing rooms to the rooms relationship of an individual residence.", + "operationId": "postResidenceRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the residence to add rooms to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the rooms to add to the rooms relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The rooms were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The residence or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "residences" + ], + "summary": "Assigns existing rooms to the rooms relationship of an individual residence.", + "operationId": "patchResidenceRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the residence whose rooms relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the rooms to assign to the rooms relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The rooms relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The residence or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "residences" + ], + "summary": "Removes existing rooms from the rooms relationship of an individual residence.", + "operationId": "deleteResidenceRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the residence to remove rooms from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the rooms to remove from the rooms relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The rooms were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The residence or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/rooms/{id}/relationships/residence": { + "get": { + "tags": [ + "rooms" + ], + "summary": "Retrieves the related residence identity of an individual room's residence relationship.", + "operationId": "getRoomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the room whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found residence identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/residenceIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The room does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "rooms" + ], + "summary": "Retrieves the related residence identity of an individual room's residence relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headRoomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the room whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The room does not exist." + } + } + }, + "patch": { + "tags": [ + "rooms" + ], + "summary": "Assigns an existing residence to the residence relationship of an individual room.", + "operationId": "patchRoomResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the room whose residence relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identity of the residence to assign to the residence relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneResidenceInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The residence relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The room or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/toilets/{id}/relationships/residence": { + "get": { + "tags": [ + "toilets" + ], + "summary": "Retrieves the related residence identity of an individual toilet's residence relationship.", + "operationId": "getToiletResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the toilet whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found residence identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/residenceIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The toilet does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "toilets" + ], + "summary": "Retrieves the related residence identity of an individual toilet's residence relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headToiletResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the toilet whose related residence identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The toilet does not exist." + } + } + }, + "patch": { + "tags": [ + "toilets" + ], + "summary": "Assigns an existing residence to the residence relationship of an individual toilet.", + "operationId": "patchToiletResidenceRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the toilet whose residence relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identity of the residence to assign to the residence relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneResidenceInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The residence relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The toilet or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "addOperationCode": { + "enum": [ + "add" + ], + "type": "string" + }, + "addToDistrictBuildingsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/districtBuildingsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/buildingIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "addToDistrictRoadsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/districtRoadsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roadIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "addToFamilyHomeRoomsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/addToResidenceRoomsRelationshipOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "addToMansionRoomsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/addToResidenceRoomsRelationshipOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "addToMansionStaffRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/mansionStaffRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staffMemberIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "addToResidenceRoomsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceRoomsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roomIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "atomicOperation": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "type": "string" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "addToDistrictBuildings": "#/components/schemas/addToDistrictBuildingsRelationshipOperation", + "addToDistrictRoads": "#/components/schemas/addToDistrictRoadsRelationshipOperation", + "addToFamilyHomeRooms": "#/components/schemas/addToFamilyHomeRoomsRelationshipOperation", + "addToMansionRooms": "#/components/schemas/addToMansionRoomsRelationshipOperation", + "addToMansionStaff": "#/components/schemas/addToMansionStaffRelationshipOperation", + "addToResidenceRooms": "#/components/schemas/addToResidenceRoomsRelationshipOperation", + "removeFromDistrictBuildings": "#/components/schemas/removeFromDistrictBuildingsRelationshipOperation", + "removeFromDistrictRoads": "#/components/schemas/removeFromDistrictRoadsRelationshipOperation", + "removeFromFamilyHomeRooms": "#/components/schemas/removeFromFamilyHomeRoomsRelationshipOperation", + "removeFromMansionRooms": "#/components/schemas/removeFromMansionRoomsRelationshipOperation", + "removeFromMansionStaff": "#/components/schemas/removeFromMansionStaffRelationshipOperation", + "removeFromResidenceRooms": "#/components/schemas/removeFromResidenceRoomsRelationshipOperation", + "updateBathroomResidence": "#/components/schemas/updateBathroomResidenceRelationshipOperation", + "updateBedroomResidence": "#/components/schemas/updateBedroomResidenceRelationshipOperation", + "updateDistrictBuildings": "#/components/schemas/updateDistrictBuildingsRelationshipOperation", + "updateDistrictRoads": "#/components/schemas/updateDistrictRoadsRelationshipOperation", + "updateFamilyHomeRooms": "#/components/schemas/updateFamilyHomeRoomsRelationshipOperation", + "updateKitchenResidence": "#/components/schemas/updateKitchenResidenceRelationshipOperation", + "updateLivingRoomResidence": "#/components/schemas/updateLivingRoomResidenceRelationshipOperation", + "updateMansionRooms": "#/components/schemas/updateMansionRoomsRelationshipOperation", + "updateMansionStaff": "#/components/schemas/updateMansionStaffRelationshipOperation", + "updateResidenceRooms": "#/components/schemas/updateResidenceRoomsRelationshipOperation", + "updateRoomResidence": "#/components/schemas/updateRoomResidenceRelationshipOperation", + "updateToiletResidence": "#/components/schemas/updateToiletResidenceRelationshipOperation" + } + }, + "x-abstract": true + }, + "atomicResult": { + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "bathroomIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "bathroomIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "bedroomIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "bedroomIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "buildingIdentifierCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/buildingIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "buildingIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "buildingIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/buildingResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "familyHomes": "#/components/schemas/familyHomeIdentifierInResponse", + "mansions": "#/components/schemas/mansionIdentifierInResponse", + "residences": "#/components/schemas/residenceIdentifierInResponse" + } + }, + "x-abstract": true + }, + "buildingResourceType": { + "enum": [ + "familyHomes", + "mansions", + "residences" + ], + "type": "string" + }, + "cyclePathIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/roadIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "cyclePathIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/roadIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "districtBuildingsRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/districtResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/districtBuildingsRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "districtBuildingsRelationshipName": { + "enum": [ + "buildings" + ], + "type": "string" + }, + "districtResourceType": { + "enum": [ + "districts" + ], + "type": "string" + }, + "districtRoadsRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/districtResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/districtRoadsRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "districtRoadsRelationshipName": { + "enum": [ + "roads" + ], + "type": "string" + }, + "errorLinks": { + "type": "object", + "properties": { + "about": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorObject": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorLinks" + } + ], + "nullable": true + }, + "status": { + "type": "string" + }, + "code": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/errorSource" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorResponseDocument": { + "required": [ + "errors", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorTopLevelLinks" + } + ] + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/errorObject" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorSource": { + "type": "object", + "properties": { + "pointer": { + "type": "string", + "nullable": true + }, + "parameter": { + "type": "string", + "nullable": true + }, + "header": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "familyHomeIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "familyHomeIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "identifierInRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "bathrooms": "#/components/schemas/bathroomIdentifierInRequest", + "bedrooms": "#/components/schemas/bedroomIdentifierInRequest", + "buildings": "#/components/schemas/buildingIdentifierInRequest", + "cyclePaths": "#/components/schemas/cyclePathIdentifierInRequest", + "familyHomes": "#/components/schemas/familyHomeIdentifierInRequest", + "kitchens": "#/components/schemas/kitchenIdentifierInRequest", + "livingRooms": "#/components/schemas/livingRoomIdentifierInRequest", + "mansions": "#/components/schemas/mansionIdentifierInRequest", + "residences": "#/components/schemas/residenceIdentifierInRequest", + "roads": "#/components/schemas/roadIdentifierInRequest", + "rooms": "#/components/schemas/roomIdentifierInRequest", + "staffMembers": "#/components/schemas/staffMemberIdentifierInRequest", + "toilets": "#/components/schemas/toiletIdentifierInRequest" + } + }, + "x-abstract": true + }, + "kitchenIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "kitchenIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "livingRoomIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "livingRoomIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "mansionIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "mansionIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "mansionResourceType": { + "enum": [ + "mansions" + ], + "type": "string" + }, + "mansionStaffRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/mansionResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/mansionStaffRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "mansionStaffRelationshipName": { + "enum": [ + "staff" + ], + "type": "string" + }, + "meta": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "operationsRequestDocument": { + "required": [ + "atomic:operations" + ], + "type": "object", + "properties": { + "atomic:operations": { + "minItems": 1, + "type": "array", + "items": { + "$ref": "#/components/schemas/atomicOperation" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "operationsResponseDocument": { + "required": [ + "atomic:results", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "atomic:results": { + "minItems": 1, + "type": "array", + "items": { + "$ref": "#/components/schemas/atomicResult" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "removeFromDistrictBuildingsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/districtBuildingsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/buildingIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "removeFromDistrictRoadsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/districtRoadsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roadIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "removeFromFamilyHomeRoomsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/removeFromResidenceRoomsRelationshipOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "removeFromMansionRoomsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/removeFromResidenceRoomsRelationshipOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "removeFromMansionStaffRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/mansionStaffRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staffMemberIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "removeFromResidenceRoomsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceRoomsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roomIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "removeOperationCode": { + "enum": [ + "remove" + ], + "type": "string" + }, + "residenceIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/buildingIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "residenceIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/buildingIdentifierInResponse" + }, + { + "required": [ + "type" + ], + "type": "object", + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "familyHomes": "#/components/schemas/familyHomeIdentifierInResponse", + "mansions": "#/components/schemas/mansionIdentifierInResponse" + } + } + } + ], + "additionalProperties": false + }, + "residenceIdentifierResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "residenceResourceType": { + "enum": [ + "familyHomes", + "mansions", + "residences" + ], + "type": "string" + }, + "residenceRoomsRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceRoomsRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "residenceRoomsRelationshipName": { + "enum": [ + "rooms" + ], + "type": "string" + }, + "resourceIdentifierCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceIdentifierTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceInResponse": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type" + }, + "x-abstract": true + }, + "resourceTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceType": { + "enum": [ + "bathrooms", + "bedrooms", + "buildings", + "cyclePaths", + "familyHomes", + "kitchens", + "livingRooms", + "mansions", + "residences", + "roads", + "rooms", + "staffMembers", + "toilets" + ], + "type": "string" + }, + "roadIdentifierCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roadIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "roadIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "roadIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/roadResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "cyclePaths": "#/components/schemas/cyclePathIdentifierInResponse" + } + } + }, + "roadResourceType": { + "enum": [ + "cyclePaths", + "roads" + ], + "type": "string" + }, + "roomIdentifierCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roomIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "roomIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "roomIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/roomResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "bathrooms": "#/components/schemas/bathroomIdentifierInResponse", + "bedrooms": "#/components/schemas/bedroomIdentifierInResponse", + "kitchens": "#/components/schemas/kitchenIdentifierInResponse", + "livingRooms": "#/components/schemas/livingRoomIdentifierInResponse", + "toilets": "#/components/schemas/toiletIdentifierInResponse" + } + }, + "x-abstract": true + }, + "roomResidenceRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/roomResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/roomResidenceRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "roomResidenceRelationshipName": { + "enum": [ + "residence" + ], + "type": "string" + }, + "roomResourceType": { + "enum": [ + "bathrooms", + "bedrooms", + "kitchens", + "livingRooms", + "toilets" + ], + "type": "string" + }, + "staffMemberIdentifierCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staffMemberIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "staffMemberIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "staffMemberIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/staffMemberResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "staffMemberResourceType": { + "enum": [ + "staffMembers" + ], + "type": "string" + }, + "toManyBuildingInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/buildingIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyRoadInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roadIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyRoomInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roomIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyStaffMemberInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staffMemberIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneResidenceInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toiletIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "toiletIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateBathroomResidenceRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/updateRoomResidenceRelationshipOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateBedroomResidenceRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/updateRoomResidenceRelationshipOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateDistrictBuildingsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/districtBuildingsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/buildingIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateDistrictRoadsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/districtRoadsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roadIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateFamilyHomeRoomsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/updateResidenceRoomsRelationshipOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateKitchenResidenceRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/updateRoomResidenceRelationshipOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateLivingRoomResidenceRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/updateRoomResidenceRelationshipOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateMansionRoomsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/updateResidenceRoomsRelationshipOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateMansionStaffRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/mansionStaffRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staffMemberIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateOperationCode": { + "enum": [ + "update" + ], + "type": "string" + }, + "updateResidenceRoomsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceRoomsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roomIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateRoomResidenceRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/roomResidenceRelationshipIdentifier" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateToiletResidenceRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/updateRoomResidenceRelationshipOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/test/OpenApiTests/ResourceInheritance/OnlyRelationships/OnlyRelationshipsEndpointFilter.cs b/test/OpenApiTests/ResourceInheritance/OnlyRelationships/OnlyRelationshipsEndpointFilter.cs new file mode 100644 index 0000000000..2425c64fb3 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/OnlyRelationships/OnlyRelationshipsEndpointFilter.cs @@ -0,0 +1,18 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; + +namespace OpenApiTests.ResourceInheritance.OnlyRelationships; + +public sealed class OnlyRelationshipsEndpointFilter : IJsonApiEndpointFilter +{ + public bool IsEnabled(ResourceType resourceType, JsonApiEndpoints endpoint) + { + return endpoint switch + { + JsonApiEndpoints.GetRelationship or JsonApiEndpoints.PostRelationship or JsonApiEndpoints.PatchRelationship or + JsonApiEndpoints.DeleteRelationship => true, + _ => false + }; + } +} diff --git a/test/OpenApiTests/ResourceInheritance/OnlyRelationships/OnlyRelationshipsInheritanceTests.cs b/test/OpenApiTests/ResourceInheritance/OnlyRelationships/OnlyRelationshipsInheritanceTests.cs new file mode 100644 index 0000000000..8d41ebaf68 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/OnlyRelationships/OnlyRelationshipsInheritanceTests.cs @@ -0,0 +1,342 @@ +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; +using Microsoft.Extensions.DependencyInjection; +using OpenApiTests.ResourceInheritance.Models; +using Xunit; +using Xunit.Abstractions; + +#pragma warning disable format + +namespace OpenApiTests.ResourceInheritance.OnlyRelationships; + +public sealed class OnlyRelationshipsInheritanceTests : ResourceInheritanceTests +{ + private const JsonApiEndpoints OnlyRelationshipEndpoints = JsonApiEndpoints.GetRelationship | JsonApiEndpoints.PostRelationship | + JsonApiEndpoints.PatchRelationship | JsonApiEndpoints.DeleteRelationship; + + public OnlyRelationshipsInheritanceTests(OpenApiTestContext, ResourceInheritanceDbContext> testContext, + ITestOutputHelper testOutputHelper) + : base(testContext, testOutputHelper, true, true) + { + testContext.ConfigureServices(services => + { + services.AddSingleton(); + services.AddSingleton(); + }); + } + + [Theory] + [InlineData(typeof(District), OnlyRelationshipEndpoints)] + [InlineData(typeof(StaffMember), OnlyRelationshipEndpoints)] + [InlineData(typeof(Building), OnlyRelationshipEndpoints)] + [InlineData(typeof(Residence), OnlyRelationshipEndpoints)] + [InlineData(typeof(FamilyHome), OnlyRelationshipEndpoints)] + [InlineData(typeof(Mansion), OnlyRelationshipEndpoints)] + [InlineData(typeof(Room), OnlyRelationshipEndpoints)] + [InlineData(typeof(Kitchen), OnlyRelationshipEndpoints)] + [InlineData(typeof(Bedroom), OnlyRelationshipEndpoints)] + [InlineData(typeof(Bathroom), OnlyRelationshipEndpoints)] + [InlineData(typeof(LivingRoom), OnlyRelationshipEndpoints)] + [InlineData(typeof(Toilet), OnlyRelationshipEndpoints)] + [InlineData(typeof(Road), OnlyRelationshipEndpoints)] + [InlineData(typeof(CyclePath), OnlyRelationshipEndpoints)] + public override async Task Only_expected_endpoints_are_exposed(Type resourceClrType, JsonApiEndpoints expected) + { + await base.Only_expected_endpoints_are_exposed(resourceClrType, expected); + } + + [Theory] + [InlineData(true)] + public override async Task Operations_endpoint_is_exposed(bool enabled) + { + await base.Operations_endpoint_is_exposed(enabled); + } + + [Theory] + [InlineData("resourceInCreateRequest", false, null)] + [InlineData("resourceInUpdateRequest", false, null)] + [InlineData("identifierInRequest", false, + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|roads|cyclePaths|staffMembers")] + [InlineData("resourceInResponse", false, "")] + [InlineData("dataInBuildingResponse", true, null)] + [InlineData("buildingIdentifierInResponse", false, "familyHomes|mansions|residences")] + [InlineData("dataInResidenceResponse", true, null)] + [InlineData("residenceIdentifierInResponse", true, "familyHomes|mansions")] + [InlineData("dataInRoomResponse", true, null)] + [InlineData("roomIdentifierInResponse", false, "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("dataInRoadResponse", true, null)] + [InlineData("roadIdentifierInResponse", false, "cyclePaths")] + public override async Task Expected_names_appear_in_type_discriminator_mapping(string schemaName, bool isWrapped, string? discriminatorValues) + { + await base.Expected_names_appear_in_type_discriminator_mapping(schemaName, isWrapped, discriminatorValues); + } + + [Theory] + [InlineData("attributesInCreateRequest", null)] + [InlineData("attributesInUpdateRequest", null)] + [InlineData("relationshipsInCreateRequest", null)] + [InlineData("relationshipsInUpdateRequest", null)] + [InlineData("!attributesInBuildingResponse", null)] + [InlineData("!relationshipsInBuildingResponse", null)] + [InlineData("!attributesInRoomResponse", null)] + [InlineData("!relationshipsInRoomResponse", null)] + [InlineData("!attributesInRoadResponse", null)] + [InlineData("!relationshipsInRoadResponse", null)] + [InlineData("atomicOperation", + // @formatter:keep_existing_linebreaks true + "addToResidenceRooms|updateResidenceRooms|removeFromResidenceRooms|" + + "addToFamilyHomeRooms|updateFamilyHomeRooms|removeFromFamilyHomeRooms|" + + "addToMansionRooms|updateMansionRooms|removeFromMansionRooms|addToMansionStaff|updateMansionStaff|removeFromMansionStaff|" + + "updateRoomResidence|" + + "updateBathroomResidence|" + + "updateBedroomResidence|" + + "updateKitchenResidence|" + + "updateLivingRoomResidence|" + + "updateToiletResidence|" + + "addToDistrictBuildings|updateDistrictBuildings|removeFromDistrictBuildings|addToDistrictRoads|updateDistrictRoads|removeFromDistrictRoads" + // @formatter:keep_existing_linebreaks restore + )] + public override async Task Expected_names_appear_in_openapi_discriminator_mapping(string schemaName, string? discriminatorValues) + { + await base.Expected_names_appear_in_openapi_discriminator_mapping(schemaName, discriminatorValues); + } + + [Theory] + [InlineData("buildingResourceType", "familyHomes|mansions|residences")] + [InlineData("residenceResourceType", "familyHomes|mansions|residences")] + [InlineData("familyHomeResourceType", null)] + [InlineData("mansionResourceType", "mansions")] + [InlineData("roomResourceType", "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("bathroomResourceType", null)] + [InlineData("bedroomResourceType", null)] + [InlineData("kitchenResourceType", null)] + [InlineData("livingRoomResourceType", null)] + [InlineData("toiletResourceType", null)] + [InlineData("roadResourceType", "roads|cyclePaths")] + [InlineData("cyclePathResourceType", null)] + [InlineData("districtResourceType", "districts")] + [InlineData("staffMemberResourceType", "staffMembers")] + [InlineData("resourceType", + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|roads|cyclePaths|staffMembers")] + public override async Task Expected_names_appear_in_resource_type_enum(string schemaName, string? enumValues) + { + await base.Expected_names_appear_in_resource_type_enum(schemaName, enumValues); + } + + [Theory] + [InlineData("resourceInCreateRequest", true, null, null)] + [InlineData("attributesInCreateRequest", true, null, null)] + [InlineData("relationshipsInCreateRequest", true, null, null)] + [InlineData("resourceInUpdateRequest", true, null, null)] + [InlineData("attributesInUpdateRequest", true, null, null)] + [InlineData("relationshipsInUpdateRequest", true, null, null)] + [InlineData("identifierInRequest", true, null, "type|meta")] + [InlineData("resourceInResponse", true, null, "type|meta")] + [InlineData("atomicOperation", true, null, "openapi:discriminator|meta")] + // Building hierarchy: Resource Data + [InlineData("dataInCreateBuildingRequest", true, null, null)] + [InlineData("dataInCreateResidenceRequest", false, null, null)] + [InlineData("dataInCreateFamilyHomeRequest", false, null, null)] + [InlineData("dataInCreateMansionRequest", false, null, null)] + [InlineData("dataInUpdateBuildingRequest", true, null, null)] + [InlineData("dataInUpdateResidenceRequest", false, null, null)] + [InlineData("dataInUpdateFamilyHomeRequest", false, null, null)] + [InlineData("dataInUpdateMansionRequest", false, null, null)] + [InlineData("dataInBuildingResponse", true, null, null)] + [InlineData("dataInResidenceResponse", false, null, null)] + [InlineData("dataInFamilyHomeResponse", false, null, null)] + [InlineData("dataInMansionResponse", false, null, null)] + // Building hierarchy: Attributes + [InlineData("attributesInCreateBuildingRequest", true, null, null)] + [InlineData("attributesInCreateResidenceRequest", false, null, null)] + [InlineData("attributesInCreateFamilyHomeRequest", false, null, null)] + [InlineData("attributesInCreateMansionRequest", false, null, null)] + [InlineData("attributesInUpdateBuildingRequest", true, null, null)] + [InlineData("attributesInUpdateResidenceRequest", false, null, null)] + [InlineData("attributesInUpdateFamilyHomeRequest", false, null, null)] + [InlineData("attributesInUpdateMansionRequest", false, null, null)] + [InlineData("attributesInBuildingResponse", true, null, null)] + [InlineData("attributesInResidenceResponse", false, null, null)] + [InlineData("attributesInFamilyHomeResponse", false, null, null)] + [InlineData("attributesInMansionResponse", false, null, null)] + // Building hierarchy: Relationships + [InlineData("relationshipsInCreateBuildingRequest", true, null, null)] + [InlineData("relationshipsInCreateResidenceRequest", false, null, null)] + [InlineData("relationshipsInCreateFamilyHomeRequest", false, null, null)] + [InlineData("relationshipsInCreateMansionRequest", false, null, null)] + [InlineData("relationshipsInUpdateBuildingRequest", true, null, null)] + [InlineData("relationshipsInUpdateResidenceRequest", false, null, null)] + [InlineData("relationshipsInUpdateFamilyHomeRequest", false, null, null)] + [InlineData("relationshipsInUpdateMansionRequest", false, null, null)] + [InlineData("relationshipsInBuildingResponse", true, null, null)] + [InlineData("relationshipsInResidenceResponse", false, null, null)] + [InlineData("relationshipsInFamilyHomeResponse", false, null, null)] + [InlineData("relationshipsInMansionResponse", false, null, null)] + // Building hierarchy: Resource Identifiers + [InlineData("buildingIdentifierInRequest", false, "identifierInRequest", "id|lid")] + [InlineData("residenceIdentifierInRequest", false, "buildingIdentifierInRequest", null)] + [InlineData("familyHomeIdentifierInRequest", false, "residenceIdentifierInRequest", null)] + [InlineData("mansionIdentifierInRequest", false, "residenceIdentifierInRequest", null)] + [InlineData("buildingIdentifierInResponse", true, null, "type|id|meta")] + [InlineData("residenceIdentifierInResponse", false, "buildingIdentifierInResponse", null)] + [InlineData("familyHomeIdentifierInResponse", false, "residenceIdentifierInResponse", null)] + [InlineData("mansionIdentifierInResponse", false, "residenceIdentifierInResponse", null)] + // Building hierarchy: Atomic Operations + [InlineData("createBuildingOperation", false, null, null)] + [InlineData("createResidenceOperation", false, null, null)] + [InlineData("createFamilyHomeOperation", false, null, null)] + [InlineData("createMansionOperation", false, null, null)] + [InlineData("updateBuildingOperation", false, null, null)] + [InlineData("updateResidenceOperation", false, null, null)] + [InlineData("updateFamilyHomeOperation", false, null, null)] + [InlineData("updateMansionOperation", false, null, null)] + [InlineData("deleteBuildingOperation", false, null, null)] + [InlineData("deleteResidenceOperation", false, null, null)] + [InlineData("deleteFamilyHomeOperation", false, null, null)] + [InlineData("deleteMansionOperation", false, null, null)] + [InlineData("updateResidenceRoomsRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateFamilyHomeRoomsRelationshipOperation", false, "updateResidenceRoomsRelationshipOperation", null)] + [InlineData("updateMansionRoomsRelationshipOperation", false, "updateResidenceRoomsRelationshipOperation", null)] + [InlineData("updateMansionStaffRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("addToResidenceRoomsRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("addToFamilyHomeRoomsRelationshipOperation", false, "addToResidenceRoomsRelationshipOperation", null)] + [InlineData("addToMansionRoomsRelationshipOperation", false, "addToResidenceRoomsRelationshipOperation", null)] + [InlineData("addToMansionStaffRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("removeFromResidenceRoomsRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("removeFromFamilyHomeRoomsRelationshipOperation", false, "removeFromResidenceRoomsRelationshipOperation", null)] + [InlineData("removeFromMansionRoomsRelationshipOperation", false, "removeFromResidenceRoomsRelationshipOperation", null)] + [InlineData("removeFromMansionStaffRelationshipOperation", false, "atomicOperation", "op|ref|data")] + // Room hierarchy: Resource Data + [InlineData("dataInCreateRoomRequest", true, null, null)] + [InlineData("dataInCreateBathroomRequest", false, null, null)] + [InlineData("dataInCreateBedroomRequest", false, null, null)] + [InlineData("dataInCreateKitchenRequest", false, null, null)] + [InlineData("dataInCreateLivingRoomRequest", false, null, null)] + [InlineData("dataInCreateToiletRequest", false, null, null)] + [InlineData("dataInUpdateRoomRequest", true, null, null)] + [InlineData("dataInUpdateBathroomRequest", false, null, null)] + [InlineData("dataInUpdateBedroomRequest", false, null, null)] + [InlineData("dataInUpdateKitchenRequest", false, null, null)] + [InlineData("dataInUpdateLivingRoomRequest", false, null, null)] + [InlineData("dataInUpdateToiletRequest", false, null, null)] + [InlineData("dataInRoomResponse", true, null, null)] + [InlineData("dataInBathroomResponse", false, null, null)] + [InlineData("dataInBedroomResponse", false, null, null)] + [InlineData("dataInKitchenResponse", false, null, null)] + [InlineData("dataInLivingRoomResponse", false, null, null)] + [InlineData("dataInToiletResponse", false, null, null)] + // Room hierarchy: Attributes + [InlineData("attributesInCreateRoomRequest", true, null, null)] + [InlineData("attributesInCreateBathroomRequest", false, null, null)] + [InlineData("attributesInCreateBedroomRequest", false, null, null)] + [InlineData("attributesInCreateKitchenRequest", false, null, null)] + [InlineData("attributesInCreateLivingRoomRequest", false, null, null)] + [InlineData("attributesInCreateToiletRequest", false, null, null)] + [InlineData("attributesInUpdateRoomRequest", true, null, null)] + [InlineData("attributesInUpdateBathroomRequest", false, null, null)] + [InlineData("attributesInUpdateBedroomRequest", false, null, null)] + [InlineData("attributesInUpdateKitchenRequest", false, null, null)] + [InlineData("attributesInUpdateLivingRoomRequest", false, null, null)] + [InlineData("attributesInUpdateToiletRequest", false, null, null)] + [InlineData("attributesInRoomResponse", true, null, null)] + [InlineData("attributesInBathroomResponse", false, null, null)] + [InlineData("attributesInBedroomResponse", false, null, null)] + [InlineData("attributesInKitchenResponse", false, null, null)] + [InlineData("attributesInLivingRoomResponse", false, null, null)] + [InlineData("attributesInToiletResponse", false, null, null)] + // Room hierarchy: Relationships + [InlineData("relationshipsInCreateRoomRequest", true, null, null)] + [InlineData("relationshipsInCreateBathroomRequest", false, null, null)] + [InlineData("relationshipsInCreateBedroomRequest", false, null, null)] + [InlineData("relationshipsInCreateKitchenRequest", false, null, null)] + [InlineData("relationshipsInCreateLivingRoomRequest", false, null, null)] + [InlineData("relationshipsInCreateToiletRequest", false, null, null)] + [InlineData("relationshipsInUpdateRoomRequest", true, null, null)] + [InlineData("relationshipsInUpdateBathroomRequest", false, null, null)] + [InlineData("relationshipsInUpdateBedroomRequest", false, null, null)] + [InlineData("relationshipsInUpdateKitchenRequest", false, null, null)] + [InlineData("relationshipsInUpdateLivingRoomRequest", false, null, null)] + [InlineData("relationshipsInUpdateToiletRequest", false, null, null)] + [InlineData("relationshipsInRoomResponse", true, null, null)] + [InlineData("relationshipsInBathroomResponse", false, null, null)] + [InlineData("relationshipsInBedroomResponse", false, null, null)] + [InlineData("relationshipsInKitchenResponse", false, null, null)] + [InlineData("relationshipsInLivingRoomResponse", false, null, null)] + [InlineData("relationshipsInToiletResponse", false, null, null)] + // Room hierarchy: Resource Identifiers + [InlineData("roomIdentifierInRequest", false, "identifierInRequest", "id|lid")] + [InlineData("bathroomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("bedroomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("kitchenIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("livingRoomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("toiletIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("roomIdentifierInResponse", true, null, "type|id|meta")] + [InlineData("bathroomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("bedroomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("kitchenIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("livingRoomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("toiletIdentifierInResponse", false, "roomIdentifierInResponse", null)] + // Room hierarchy: Atomic Operations + [InlineData("createRoomOperation", false, null, null)] + [InlineData("createBathroomOperation", false, null, null)] + [InlineData("createBedroomOperation", false, null, null)] + [InlineData("createKitchenOperation", false, null, null)] + [InlineData("createLivingRoomOperation", false, null, null)] + [InlineData("createToiletOperation", false, null, null)] + [InlineData("updateRoomOperation", false, null, null)] + [InlineData("updateBathroomOperation", false, null, null)] + [InlineData("updateBedroomOperation", false, null, null)] + [InlineData("updateKitchenOperation", false, null, null)] + [InlineData("updateLivingRoomOperation", false, null, null)] + [InlineData("updateToiletOperation", false, null, null)] + [InlineData("deleteRoomOperation", false, null, null)] + [InlineData("deleteBathroomOperation", false, null, null)] + [InlineData("deleteBedroomOperation", false, null, null)] + [InlineData("deleteKitchenOperation", false, null, null)] + [InlineData("deleteLivingRoomOperation", false, null, null)] + [InlineData("deleteToiletOperation", false, null, null)] + [InlineData("updateRoomResidenceRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateBathroomResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + [InlineData("updateBedroomResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + [InlineData("updateKitchenResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + [InlineData("updateLivingRoomResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + [InlineData("updateToiletResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + // Road hierarchy: Resource Data + [InlineData("dataInCreateRoadRequest", false, null, null)] + [InlineData("dataInCreateCyclePathRequest", false, null, null)] + [InlineData("dataInUpdateRoadRequest", false, null, null)] + [InlineData("dataInUpdateCyclePathRequest", false, null, null)] + [InlineData("dataInRoadResponse", false, null, null)] + [InlineData("dataInCyclePathResponse", false, null, null)] + // Road hierarchy: Attributes + [InlineData("attributesInCreateRoadRequest", false, null, null)] + [InlineData("attributesInCreateCyclePathRequest", false, null, null)] + [InlineData("attributesInUpdateRoadRequest", false, null, null)] + [InlineData("attributesInUpdateCyclePathRequest", false, null, null)] + [InlineData("attributesInRoadResponse", false, null, null)] + [InlineData("attributesInCyclePathResponse", false, null, null)] + // Road hierarchy: Relationships + [InlineData("relationshipsInCreateRoadRequest", false, null, null)] + [InlineData("relationshipsInCreateCyclePathRequest", false, null, null)] + [InlineData("relationshipsInUpdateRoadRequest", false, null, null)] + [InlineData("relationshipsInUpdateCyclePathRequest", false, null, null)] + [InlineData("relationshipsInRoadResponse", false, null, null)] + [InlineData("relationshipsInCyclePathResponse", false, null, null)] + // Road hierarchy: Resource Identifiers + [InlineData("roadIdentifierInRequest", false, "identifierInRequest", "id|lid")] + [InlineData("cyclePathIdentifierInRequest", false, "roadIdentifierInRequest", null)] + [InlineData("roadIdentifierInResponse", false, null, "type|id|meta")] + [InlineData("cyclePathIdentifierInResponse", false, "roadIdentifierInResponse", null)] + // Road hierarchy: Atomic Operations + [InlineData("createRoadOperation", false, null, null)] + [InlineData("createCyclePathOperation", false, null, null)] + [InlineData("updateRoadOperation", false, null, null)] + [InlineData("updateCyclePathOperation", false, null, null)] + [InlineData("deleteRoadOperation", false, null, null)] + [InlineData("deleteCyclePathOperation", false, null, null)] + public override async Task Component_schemas_have_expected_base_type(string schemaName, bool isAbstract, string? baseType, string? properties) + { + await base.Component_schemas_have_expected_base_type(schemaName, isAbstract, baseType, properties); + } +} diff --git a/test/OpenApiTests/ResourceInheritance/OnlyRelationships/OnlyRelationshipsOperationFilter.cs b/test/OpenApiTests/ResourceInheritance/OnlyRelationships/OnlyRelationshipsOperationFilter.cs new file mode 100644 index 0000000000..528990caa3 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/OnlyRelationships/OnlyRelationshipsOperationFilter.cs @@ -0,0 +1,13 @@ +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; + +namespace OpenApiTests.ResourceInheritance.OnlyRelationships; + +public sealed class OnlyRelationshipsOperationFilter : DefaultOperationFilter +{ + protected override JsonApiEndpoints? GetJsonApiEndpoints(ResourceType resourceType) + { + return JsonApiEndpoints.GetRelationship | JsonApiEndpoints.PostRelationship | JsonApiEndpoints.PatchRelationship | JsonApiEndpoints.DeleteRelationship; + } +} diff --git a/test/OpenApiTests/ResourceInheritance/OperationsController.cs b/test/OpenApiTests/ResourceInheritance/OperationsController.cs new file mode 100644 index 0000000000..ba56ca89b2 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/OperationsController.cs @@ -0,0 +1,13 @@ +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; +using JsonApiDotNetCore.Resources; +using Microsoft.Extensions.Logging; + +namespace OpenApiTests.ResourceInheritance; + +public sealed class OperationsController( + IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, IOperationsProcessor processor, IJsonApiRequest request, + ITargetedFields targetedFields, IAtomicOperationFilter operationFilter) + : JsonApiOperationsController(options, resourceGraph, loggerFactory, processor, request, targetedFields, operationFilter); diff --git a/test/OpenApiTests/ResourceInheritance/ResourceInheritanceControllerExtensions.cs b/test/OpenApiTests/ResourceInheritance/ResourceInheritanceControllerExtensions.cs new file mode 100644 index 0000000000..8856301cb9 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/ResourceInheritanceControllerExtensions.cs @@ -0,0 +1,35 @@ +using TestBuildingBlocks; + +namespace OpenApiTests.ResourceInheritance; + +public static class ResourceInheritanceControllerExtensions +{ + public static void UseInheritanceControllers( + this IntegrationTestContext, ResourceInheritanceDbContext> testContext, bool hasOperationsController) + { + ArgumentNullException.ThrowIfNull(testContext); + + testContext.UseController(); + testContext.UseController(); + + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + + testContext.UseController(); + testContext.UseController(); + + if (hasOperationsController) + { + testContext.UseController(); + } + } +} diff --git a/test/OpenApiTests/ResourceInheritance/ResourceInheritanceDbContext.cs b/test/OpenApiTests/ResourceInheritance/ResourceInheritanceDbContext.cs new file mode 100644 index 0000000000..182282bf87 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/ResourceInheritanceDbContext.cs @@ -0,0 +1,29 @@ +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; +using OpenApiTests.ResourceInheritance.Models; +using TestBuildingBlocks; + +namespace OpenApiTests.ResourceInheritance; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public sealed class ResourceInheritanceDbContext(DbContextOptions options) + : TestableDbContext(options) +{ + public DbSet Districts => Set(); + public DbSet StaffMembers => Set(); + + public DbSet Buildings => Set(); + public DbSet Residences => Set(); + public DbSet FamilyHomes => Set(); + public DbSet Mansions => Set(); + + public DbSet Rooms => Set(); + public DbSet Kitchens => Set(); + public DbSet Bedrooms => Set(); + public DbSet Bathrooms => Set(); + public DbSet LivingRooms => Set(); + public DbSet Toilets => Set(); + + public DbSet Roads => Set(); + public DbSet CyclePaths => Set(); +} diff --git a/test/OpenApiTests/ResourceInheritance/ResourceInheritanceFakers.cs b/test/OpenApiTests/ResourceInheritance/ResourceInheritanceFakers.cs new file mode 100644 index 0000000000..2e45c2bf0e --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/ResourceInheritanceFakers.cs @@ -0,0 +1,85 @@ +using Bogus; +using JetBrains.Annotations; +using OpenApiTests.ResourceInheritance.Models; +using TestBuildingBlocks; + +// @formatter:wrap_chained_method_calls chop_if_long +// @formatter:wrap_before_first_method_call true + +namespace OpenApiTests.ResourceInheritance; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public sealed class ResourceInheritanceFakers +{ + private readonly Lazy> _lazyDistrictFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(district => district.Name, faker => faker.Address.County())); + + private readonly Lazy> _lazyStaffMemberFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(staffMember => staffMember.Name, faker => faker.Person.FullName)); + + private readonly Lazy> _lazyResidenceFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(residence => residence.SurfaceInSquareMeters, faker => faker.Random.Int(50, 250)) + .RuleFor(residence => residence.NumberOfResidents, faker => faker.Random.Int(0, 15))); + + private readonly Lazy> _lazyMansionFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(mansion => mansion.SurfaceInSquareMeters, faker => faker.Random.Int(500, 2500)) + .RuleFor(mansion => mansion.NumberOfResidents, faker => faker.Random.Int(0, 150)) + .RuleFor(mansion => mansion.OwnerName, faker => faker.Person.FullName)); + + private readonly Lazy> _lazyFamilyHomeFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(familyHome => familyHome.SurfaceInSquareMeters, faker => faker.Random.Int(500, 2500)) + .RuleFor(familyHome => familyHome.NumberOfResidents, faker => faker.Random.Int(0, 150)) + .RuleFor(familyHome => familyHome.FloorCount, faker => faker.Random.Int(1, 4))); + + private readonly Lazy> _lazyKitchenFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(kitchen => kitchen.SurfaceInSquareMeters, faker => faker.Random.Int(50, 250)) + .RuleFor(kitchen => kitchen.HasPantry, faker => faker.Random.Bool())); + + private readonly Lazy> _lazyBedroomFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(bedroom => bedroom.SurfaceInSquareMeters, faker => faker.Random.Int(50, 250)) + .RuleFor(bedroom => bedroom.BedCount, faker => faker.Random.Int(1, 5))); + + private readonly Lazy> _lazyBathroomFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(bathroom => bathroom.SurfaceInSquareMeters, faker => faker.Random.Int(50, 250)) + .RuleFor(bathroom => bathroom.HasBath, faker => faker.Random.Bool())); + + private readonly Lazy> _lazyLivingRoomFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(livingRoom => livingRoom.SurfaceInSquareMeters, faker => faker.Random.Int(50, 250)) + .RuleFor(livingRoom => livingRoom.HasDiningTable, faker => faker.Random.Bool())); + + private readonly Lazy> _lazyToiletFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(toilet => toilet.SurfaceInSquareMeters, faker => faker.Random.Int(50, 250)) + .RuleFor(toilet => toilet.HasSink, faker => faker.Random.Bool())); + + private readonly Lazy> _lazyRoadFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(road => road.LengthInMeters, faker => faker.Random.Int(20, 2500))); + + private readonly Lazy> _lazyCyclePathFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(cyclePath => cyclePath.LengthInMeters, faker => faker.Random.Int(20, 2500)) + .RuleFor(cyclePath => cyclePath.HasLaneForPedestrians, faker => faker.Random.Bool())); + + public Faker District => _lazyDistrictFaker.Value; + public Faker StaffMember => _lazyStaffMemberFaker.Value; + public Faker Residence => _lazyResidenceFaker.Value; + public Faker FamilyHome => _lazyFamilyHomeFaker.Value; + public Faker Mansion => _lazyMansionFaker.Value; + public Faker Kitchen => _lazyKitchenFaker.Value; + public Faker Bedroom => _lazyBedroomFaker.Value; + public Faker Bathroom => _lazyBathroomFaker.Value; + public Faker LivingRoom => _lazyLivingRoomFaker.Value; + public Faker Toilet => _lazyToiletFaker.Value; + public Faker Road => _lazyRoadFaker.Value; + public Faker CyclePath => _lazyCyclePathFaker.Value; +} diff --git a/test/OpenApiTests/ResourceInheritance/ResourceInheritanceTests.cs b/test/OpenApiTests/ResourceInheritance/ResourceInheritanceTests.cs new file mode 100644 index 0000000000..7455c0c899 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/ResourceInheritanceTests.cs @@ -0,0 +1,256 @@ +using System.Collections.ObjectModel; +using System.Text.Json; +using FluentAssertions; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using Microsoft.Extensions.DependencyInjection; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +#pragma warning disable AV1755 // Name of async method should end with Async or TaskAsync + +namespace OpenApiTests.ResourceInheritance; + +public abstract class ResourceInheritanceTests : IClassFixture, ResourceInheritanceDbContext>> +{ + private readonly OpenApiTestContext, ResourceInheritanceDbContext> _testContext; + + protected ResourceInheritanceTests(OpenApiTestContext, ResourceInheritanceDbContext> testContext, + ITestOutputHelper testOutputHelper, bool hasOperationsController, bool writeToDisk) + { + _testContext = testContext; + + testContext.UseInheritanceControllers(hasOperationsController); + testContext.SetTestOutputHelper(testOutputHelper); + + if (writeToDisk) + { + testContext.SwaggerDocumentOutputDirectory = $"{GetType().Namespace!.Replace('.', '/')}/GeneratedSwagger"; + } + } + + public virtual async Task Only_expected_endpoints_are_exposed(Type resourceClrType, JsonApiEndpoints expected) + { + // Arrange + var resourceGraph = _testContext.Factory.Services.GetRequiredService(); + ResourceType resourceType = resourceGraph.GetResourceType(resourceClrType); + IReadOnlyDictionary> endpointToPathMap = JsonPathBuilder.GetEndpointPaths(resourceType); + + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + string[] pathsExpected = JsonPathBuilder.KnownEndpoints.Where(endpoint => expected.HasFlag(endpoint)) + .SelectMany(endpoint => endpointToPathMap[endpoint]).ToArray(); + + string[] pathsNotExpected = endpointToPathMap.Values.SelectMany(paths => paths).Except(pathsExpected).ToArray(); + + foreach (string path in pathsExpected) + { + document.Should().ContainPath(path); + } + + foreach (string path in pathsNotExpected) + { + document.Should().NotContainPath(path); + } + } + + public virtual async Task Operations_endpoint_is_exposed(bool enabled) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + if (enabled) + { + document.Should().ContainPath("paths./operations.post"); + } + else + { + document.Should().NotContainPath("paths./operations.post"); + } + } + + public virtual async Task Expected_names_appear_in_type_discriminator_mapping(string schemaName, bool isWrapped, string? discriminatorValues) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + if (discriminatorValues == null) + { + document.Should().NotContainPath($"components.schemas.{schemaName}"); + } + else + { + string schemaPath = isWrapped ? $"components.schemas.{schemaName}.allOf[1]" : $"components.schemas.{schemaName}"; + + document.Should().ContainPath(schemaPath).With(schemaElement => + { + schemaElement.Should().ContainPath("discriminator").With(discriminatorElement => + { + discriminatorElement.Should().HaveProperty("propertyName", "type"); + + if (discriminatorValues.Length == 0) + { + discriminatorElement.Should().NotContainPath("mapping"); + } + else + { + discriminatorElement.Should().ContainPath("mapping").With(mappingElement => + { + string[] valueArray = discriminatorValues.Split('|'); + mappingElement.EnumerateObject().Should().HaveCount(valueArray.Length); + + foreach (string value in valueArray) + { + mappingElement.Should().ContainProperty(value); + } + }); + } + }); + }); + } + } + + public virtual async Task Expected_names_appear_in_openapi_discriminator_mapping(string prefixedSchemaName, string? discriminatorValues) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + string schemaName = prefixedSchemaName.StartsWith('!') ? prefixedSchemaName[1..] : prefixedSchemaName; + string discriminatorPath = prefixedSchemaName.StartsWith('!') ? "allOf[1].discriminator" : "discriminator"; + + // Assert + if (discriminatorValues == null) + { + document.Should().NotContainPath($"components.schemas.{schemaName}"); + } + else + { + document.Should().ContainPath($"components.schemas.{schemaName}").With(schemaElement => + { + schemaElement.Should().ContainPath(discriminatorPath).With(discriminatorElement => + { + discriminatorElement.Should().HaveProperty("propertyName", "openapi:discriminator"); + + if (discriminatorValues.Length == 0) + { + discriminatorElement.Should().NotContainPath("mapping"); + } + else + { + discriminatorElement.Should().ContainPath("mapping").With(mappingElement => + { + string[] valueArray = discriminatorValues.Split('|'); + mappingElement.EnumerateObject().Should().HaveCount(valueArray.Length); + + foreach (string value in valueArray) + { + mappingElement.Should().ContainProperty(value); + } + }); + } + }); + }); + } + } + + public virtual async Task Expected_names_appear_in_resource_type_enum(string schemaName, string? enumValues) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + if (enumValues == null) + { + document.Should().NotContainPath($"components.schemas.{schemaName}"); + } + else + { + document.Should().ContainPath($"components.schemas.{schemaName}").With(schemaElement => + { + if (enumValues.Length == 0) + { + schemaElement.Should().NotContainPath("enum"); + } + else + { + schemaElement.Should().ContainPath("enum").With(enumElement => + { + string[] valueArray = enumValues.Split('|'); + enumElement.EnumerateArray().Should().HaveCount(valueArray.Length); + + foreach (string value in valueArray) + { + enumElement.Should().ContainArrayElement(value); + } + }); + } + }); + } + } + + public virtual async Task Component_schemas_have_expected_base_type(string schemaName, bool isAbstract, string? baseType, string? properties) + { + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + if (baseType == null && properties == null) + { + document.Should().NotContainPath($"components.schemas.{schemaName}"); + } + else + { + document.Should().ContainPath($"components.schemas.{schemaName}").With(schemaElement => + { + if (baseType == null) + { + schemaElement.Should().NotContainPath("allOf[0]"); + } + else + { + schemaElement.Should().HaveProperty("allOf[0].$ref", $"#/components/schemas/{baseType}"); + } + + string propertiesPath = baseType != null ? "allOf[1].properties" : "properties"; + + if (properties == null) + { + schemaElement.Should().NotContainPath(propertiesPath); + } + else + { + string[] propertyArray = properties.Split('|'); + + schemaElement.Should().ContainPath(propertiesPath).With(propertiesElement => + { + propertiesElement.EnumerateObject().Should().HaveCount(propertyArray.Length); + + foreach (string value in propertyArray) + { + propertiesElement.Should().ContainProperty(value); + } + }); + } + + string abstractPath = baseType != null ? "allOf[1].x-abstract" : "x-abstract"; + + if (!isAbstract) + { + schemaElement.Should().NotContainPath(abstractPath); + } + else + { + schemaElement.Should().ContainPath(abstractPath).With(abstractElement => + { + abstractElement.Should().Be(true); + }); + } + }); + } + } +} diff --git a/test/OpenApiTests/ResourceInheritance/SubsetOfOperations/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/ResourceInheritance/SubsetOfOperations/GeneratedSwagger/swagger.g.json new file mode 100644 index 0000000000..88e0ed9f8d --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/SubsetOfOperations/GeneratedSwagger/swagger.g.json @@ -0,0 +1,3258 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "OpenApiTests", + "version": "1.0" + }, + "servers": [ + { + "url": "http://localhost" + } + ], + "paths": { + "/operations": { + "post": { + "tags": [ + "operations" + ], + "summary": "Performs multiple mutations in a linear and atomic manner.", + "operationId": "postOperations", + "requestBody": { + "description": "An array of mutation operations. For syntax, see the [Atomic Operations documentation](https://jsonapi.org/ext/atomic/).", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/operationsRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "All operations were successfully applied, which resulted in additional changes.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/operationsResponseDocument" + } + } + } + }, + "204": { + "description": "All operations were successfully applied, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "An operation is not accessible or a client-generated ID is used.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A resource or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=atomic; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "addOperationCode": { + "enum": [ + "add" + ], + "type": "string" + }, + "addToFamilyHomeRoomsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/familyHomeRoomsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roomIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "atomicOperation": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "type": "string" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "addBathroom": "#/components/schemas/createBathroomOperation", + "addBedroom": "#/components/schemas/createBedroomOperation", + "addFamilyHome": "#/components/schemas/createFamilyHomeOperation", + "addKitchen": "#/components/schemas/createKitchenOperation", + "addLivingRoom": "#/components/schemas/createLivingRoomOperation", + "addMansion": "#/components/schemas/createMansionOperation", + "addResidence": "#/components/schemas/createResidenceOperation", + "addRoom": "#/components/schemas/createRoomOperation", + "addToFamilyHomeRooms": "#/components/schemas/addToFamilyHomeRoomsRelationshipOperation", + "addToilet": "#/components/schemas/createToiletOperation", + "removeFromMansionRooms": "#/components/schemas/removeFromMansionRoomsRelationshipOperation", + "removeFromMansionStaff": "#/components/schemas/removeFromMansionStaffRelationshipOperation", + "updateBathroomResidence": "#/components/schemas/updateBathroomResidenceRelationshipOperation", + "updateBedroomResidence": "#/components/schemas/updateBedroomResidenceRelationshipOperation", + "updateFamilyHome": "#/components/schemas/updateFamilyHomeOperation", + "updateKitchenResidence": "#/components/schemas/updateKitchenResidenceRelationshipOperation", + "updateLivingRoomResidence": "#/components/schemas/updateLivingRoomResidenceRelationshipOperation", + "updateMansion": "#/components/schemas/updateMansionOperation", + "updateResidence": "#/components/schemas/updateResidenceOperation", + "updateRoomResidence": "#/components/schemas/updateRoomResidenceRelationshipOperation", + "updateToiletResidence": "#/components/schemas/updateToiletResidenceRelationshipOperation" + } + }, + "x-abstract": true + }, + "atomicResult": { + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "attributesInBathroomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInRoomResponse" + }, + { + "type": "object", + "properties": { + "hasBath": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInBedroomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInRoomResponse" + }, + { + "type": "object", + "properties": { + "bedCount": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInBuildingResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "surfaceInSquareMeters": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "familyHomes": "#/components/schemas/attributesInFamilyHomeResponse", + "mansions": "#/components/schemas/attributesInMansionResponse", + "residences": "#/components/schemas/attributesInResidenceResponse" + } + }, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "attributesInCreateBathroomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRoomRequest" + }, + { + "required": [ + "hasBath" + ], + "type": "object", + "properties": { + "hasBath": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateBedroomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRoomRequest" + }, + { + "required": [ + "bedCount" + ], + "type": "object", + "properties": { + "bedCount": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateBuildingRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "surfaceInSquareMeters" + ], + "type": "object", + "properties": { + "surfaceInSquareMeters": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "attributesInCreateFamilyHomeRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateResidenceRequest" + }, + { + "type": "object", + "properties": { + "floorCount": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateKitchenRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRoomRequest" + }, + { + "required": [ + "hasPantry" + ], + "type": "object", + "properties": { + "hasPantry": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateLivingRoomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRoomRequest" + }, + { + "required": [ + "hasDiningTable" + ], + "type": "object", + "properties": { + "hasDiningTable": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateMansionRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateResidenceRequest" + }, + { + "required": [ + "ownerName" + ], + "type": "object", + "properties": { + "ownerName": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "bathrooms": "#/components/schemas/attributesInCreateBathroomRequest", + "bedrooms": "#/components/schemas/attributesInCreateBedroomRequest", + "buildings": "#/components/schemas/attributesInCreateBuildingRequest", + "familyHomes": "#/components/schemas/attributesInCreateFamilyHomeRequest", + "kitchens": "#/components/schemas/attributesInCreateKitchenRequest", + "livingRooms": "#/components/schemas/attributesInCreateLivingRoomRequest", + "mansions": "#/components/schemas/attributesInCreateMansionRequest", + "residences": "#/components/schemas/attributesInCreateResidenceRequest", + "rooms": "#/components/schemas/attributesInCreateRoomRequest", + "toilets": "#/components/schemas/attributesInCreateToiletRequest" + } + }, + "x-abstract": true + }, + "attributesInCreateResidenceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateBuildingRequest" + }, + { + "required": [ + "numberOfResidents" + ], + "type": "object", + "properties": { + "numberOfResidents": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateRoomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "surfaceInSquareMeters" + ], + "type": "object", + "properties": { + "surfaceInSquareMeters": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "attributesInCreateToiletRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRoomRequest" + }, + { + "required": [ + "hasSink" + ], + "type": "object", + "properties": { + "hasSink": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInFamilyHomeResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResidenceResponse" + }, + { + "type": "object", + "properties": { + "floorCount": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInKitchenResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInRoomResponse" + }, + { + "type": "object", + "properties": { + "hasPantry": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInLivingRoomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInRoomResponse" + }, + { + "type": "object", + "properties": { + "hasDiningTable": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInMansionResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResidenceResponse" + }, + { + "type": "object", + "properties": { + "ownerName": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInResidenceResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInBuildingResponse" + }, + { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "numberOfResidents": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "familyHomes": "#/components/schemas/attributesInFamilyHomeResponse", + "mansions": "#/components/schemas/attributesInMansionResponse" + } + } + } + ], + "additionalProperties": false + }, + "attributesInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "bathrooms": "#/components/schemas/attributesInBathroomResponse", + "bedrooms": "#/components/schemas/attributesInBedroomResponse", + "buildings": "#/components/schemas/attributesInBuildingResponse", + "familyHomes": "#/components/schemas/attributesInFamilyHomeResponse", + "kitchens": "#/components/schemas/attributesInKitchenResponse", + "livingRooms": "#/components/schemas/attributesInLivingRoomResponse", + "mansions": "#/components/schemas/attributesInMansionResponse", + "residences": "#/components/schemas/attributesInResidenceResponse", + "rooms": "#/components/schemas/attributesInRoomResponse", + "toilets": "#/components/schemas/attributesInToiletResponse" + } + }, + "x-abstract": true + }, + "attributesInRoomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "surfaceInSquareMeters": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "bathrooms": "#/components/schemas/attributesInBathroomResponse", + "bedrooms": "#/components/schemas/attributesInBedroomResponse", + "kitchens": "#/components/schemas/attributesInKitchenResponse", + "livingRooms": "#/components/schemas/attributesInLivingRoomResponse", + "toilets": "#/components/schemas/attributesInToiletResponse" + } + }, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "attributesInToiletResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInRoomResponse" + }, + { + "type": "object", + "properties": { + "hasSink": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateBuildingRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "surfaceInSquareMeters": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "attributesInUpdateFamilyHomeRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateResidenceRequest" + }, + { + "type": "object", + "properties": { + "floorCount": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateMansionRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateResidenceRequest" + }, + { + "type": "object", + "properties": { + "ownerName": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "buildings": "#/components/schemas/attributesInUpdateBuildingRequest", + "familyHomes": "#/components/schemas/attributesInUpdateFamilyHomeRequest", + "mansions": "#/components/schemas/attributesInUpdateMansionRequest", + "residences": "#/components/schemas/attributesInUpdateResidenceRequest" + } + }, + "x-abstract": true + }, + "attributesInUpdateResidenceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateBuildingRequest" + }, + { + "type": "object", + "properties": { + "numberOfResidents": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "bathroomIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "bathroomIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "bedroomIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "bedroomIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "buildingIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "buildingIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/buildingResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "familyHomes": "#/components/schemas/familyHomeIdentifierInResponse", + "mansions": "#/components/schemas/mansionIdentifierInResponse", + "residences": "#/components/schemas/residenceIdentifierInResponse" + } + }, + "x-abstract": true + }, + "buildingResourceType": { + "enum": [ + "familyHomes", + "mansions", + "residences" + ], + "type": "string" + }, + "createBathroomOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/createRoomOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createBedroomOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/createRoomOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createFamilyHomeOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/createResidenceOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createKitchenOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/createRoomOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createLivingRoomOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/createRoomOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createMansionOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/createResidenceOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createResidenceOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateResidenceRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createRoomOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/addOperationCode" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateRoomRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createToiletOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/createRoomOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInBathroomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInBedroomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInBuildingResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInBuildingResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInBuildingResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "familyHomes": "#/components/schemas/dataInFamilyHomeResponse", + "mansions": "#/components/schemas/dataInMansionResponse", + "residences": "#/components/schemas/dataInResidenceResponse" + } + }, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "dataInCreateBathroomRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateBedroomRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateBuildingRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateBuildingRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateBuildingRequest" + } + ] + } + }, + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "dataInCreateFamilyHomeRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateResidenceRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateKitchenRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateLivingRoomRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateMansionRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateResidenceRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateResidenceRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateBuildingRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateRoomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRoomRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRoomRequest" + } + ] + } + }, + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "dataInCreateToiletRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInFamilyHomeResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInResidenceResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInKitchenResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInLivingRoomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInMansionResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInResidenceResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInResidenceResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInBuildingResponse" + }, + { + "required": [ + "type" + ], + "type": "object", + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "familyHomes": "#/components/schemas/dataInFamilyHomeResponse", + "mansions": "#/components/schemas/dataInMansionResponse" + } + } + } + ], + "additionalProperties": false + }, + "dataInRoomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInRoomResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInRoomResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "bathrooms": "#/components/schemas/dataInBathroomResponse", + "bedrooms": "#/components/schemas/dataInBedroomResponse", + "kitchens": "#/components/schemas/dataInKitchenResponse", + "livingRooms": "#/components/schemas/dataInLivingRoomResponse", + "toilets": "#/components/schemas/dataInToiletResponse" + } + }, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "dataInToiletResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateBuildingRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateBuildingRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateBuildingRequest" + } + ] + } + }, + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "dataInUpdateFamilyHomeRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateResidenceRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateMansionRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateResidenceRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateResidenceRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateBuildingRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "errorLinks": { + "type": "object", + "properties": { + "about": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorObject": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorLinks" + } + ], + "nullable": true + }, + "status": { + "type": "string" + }, + "code": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/errorSource" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorResponseDocument": { + "required": [ + "errors", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorTopLevelLinks" + } + ] + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/errorObject" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorSource": { + "type": "object", + "properties": { + "pointer": { + "type": "string", + "nullable": true + }, + "parameter": { + "type": "string", + "nullable": true + }, + "header": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "familyHomeIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "familyHomeIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "familyHomeResourceType": { + "enum": [ + "familyHomes" + ], + "type": "string" + }, + "familyHomeRoomsRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/familyHomeResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/familyHomeRoomsRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "familyHomeRoomsRelationshipName": { + "enum": [ + "rooms" + ], + "type": "string" + }, + "identifierInRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "bathrooms": "#/components/schemas/bathroomIdentifierInRequest", + "bedrooms": "#/components/schemas/bedroomIdentifierInRequest", + "buildings": "#/components/schemas/buildingIdentifierInRequest", + "familyHomes": "#/components/schemas/familyHomeIdentifierInRequest", + "kitchens": "#/components/schemas/kitchenIdentifierInRequest", + "livingRooms": "#/components/schemas/livingRoomIdentifierInRequest", + "mansions": "#/components/schemas/mansionIdentifierInRequest", + "residences": "#/components/schemas/residenceIdentifierInRequest", + "rooms": "#/components/schemas/roomIdentifierInRequest", + "staffMembers": "#/components/schemas/staffMemberIdentifierInRequest", + "toilets": "#/components/schemas/toiletIdentifierInRequest" + } + }, + "x-abstract": true + }, + "kitchenIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "kitchenIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "livingRoomIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "livingRoomIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "mansionIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "mansionIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "mansionResourceType": { + "enum": [ + "mansions" + ], + "type": "string" + }, + "mansionRoomsRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/mansionResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/mansionRoomsRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "mansionRoomsRelationshipName": { + "enum": [ + "rooms" + ], + "type": "string" + }, + "mansionStaffRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/mansionResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/mansionStaffRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "mansionStaffRelationshipName": { + "enum": [ + "staff" + ], + "type": "string" + }, + "meta": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "operationsRequestDocument": { + "required": [ + "atomic:operations" + ], + "type": "object", + "properties": { + "atomic:operations": { + "minItems": 1, + "type": "array", + "items": { + "$ref": "#/components/schemas/atomicOperation" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "operationsResponseDocument": { + "required": [ + "atomic:results", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "atomic:results": { + "minItems": 1, + "type": "array", + "items": { + "$ref": "#/components/schemas/atomicResult" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "relationshipLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + } + }, + "additionalProperties": false + }, + "relationshipsInBathroomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInBedroomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInBuildingResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "familyHomes": "#/components/schemas/relationshipsInFamilyHomeResponse", + "mansions": "#/components/schemas/relationshipsInMansionResponse", + "residences": "#/components/schemas/relationshipsInResidenceResponse" + } + }, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "relationshipsInCreateBathroomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateBedroomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateBuildingRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "type": "object", + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "relationshipsInCreateFamilyHomeRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateResidenceRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateKitchenRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateLivingRoomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateMansionRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateResidenceRequest" + }, + { + "type": "object", + "properties": { + "staff": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStaffMemberInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "bathrooms": "#/components/schemas/relationshipsInCreateBathroomRequest", + "bedrooms": "#/components/schemas/relationshipsInCreateBedroomRequest", + "buildings": "#/components/schemas/relationshipsInCreateBuildingRequest", + "familyHomes": "#/components/schemas/relationshipsInCreateFamilyHomeRequest", + "kitchens": "#/components/schemas/relationshipsInCreateKitchenRequest", + "livingRooms": "#/components/schemas/relationshipsInCreateLivingRoomRequest", + "mansions": "#/components/schemas/relationshipsInCreateMansionRequest", + "residences": "#/components/schemas/relationshipsInCreateResidenceRequest", + "rooms": "#/components/schemas/relationshipsInCreateRoomRequest", + "toilets": "#/components/schemas/relationshipsInCreateToiletRequest" + } + }, + "x-abstract": true + }, + "relationshipsInCreateResidenceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateBuildingRequest" + }, + { + "type": "object", + "properties": { + "rooms": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateRoomRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "required": [ + "residence" + ], + "type": "object", + "properties": { + "residence": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneResidenceInRequest" + } + ] + } + }, + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "relationshipsInCreateToiletRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRoomRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInFamilyHomeResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResidenceResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInKitchenResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInLivingRoomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInMansionResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResidenceResponse" + }, + { + "type": "object", + "properties": { + "staff": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStaffMemberInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInResidenceResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInBuildingResponse" + }, + { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "rooms": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInResponse" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "familyHomes": "#/components/schemas/relationshipsInFamilyHomeResponse", + "mansions": "#/components/schemas/relationshipsInMansionResponse" + } + } + } + ], + "additionalProperties": false + }, + "relationshipsInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "bathrooms": "#/components/schemas/relationshipsInBathroomResponse", + "bedrooms": "#/components/schemas/relationshipsInBedroomResponse", + "buildings": "#/components/schemas/relationshipsInBuildingResponse", + "familyHomes": "#/components/schemas/relationshipsInFamilyHomeResponse", + "kitchens": "#/components/schemas/relationshipsInKitchenResponse", + "livingRooms": "#/components/schemas/relationshipsInLivingRoomResponse", + "mansions": "#/components/schemas/relationshipsInMansionResponse", + "residences": "#/components/schemas/relationshipsInResidenceResponse", + "rooms": "#/components/schemas/relationshipsInRoomResponse", + "toilets": "#/components/schemas/relationshipsInToiletResponse" + } + }, + "x-abstract": true + }, + "relationshipsInRoomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "residence": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneResidenceInResponse" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "bathrooms": "#/components/schemas/relationshipsInBathroomResponse", + "bedrooms": "#/components/schemas/relationshipsInBedroomResponse", + "kitchens": "#/components/schemas/relationshipsInKitchenResponse", + "livingRooms": "#/components/schemas/relationshipsInLivingRoomResponse", + "toilets": "#/components/schemas/relationshipsInToiletResponse" + } + }, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "relationshipsInToiletResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateBuildingRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateFamilyHomeRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateResidenceRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateMansionRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateResidenceRequest" + }, + { + "type": "object", + "properties": { + "staff": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStaffMemberInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "buildings": "#/components/schemas/relationshipsInUpdateBuildingRequest", + "familyHomes": "#/components/schemas/relationshipsInUpdateFamilyHomeRequest", + "mansions": "#/components/schemas/relationshipsInUpdateMansionRequest", + "residences": "#/components/schemas/relationshipsInUpdateResidenceRequest" + } + }, + "x-abstract": true + }, + "relationshipsInUpdateResidenceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateBuildingRequest" + }, + { + "type": "object", + "properties": { + "rooms": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "removeFromMansionRoomsRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/mansionRoomsRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roomIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "removeFromMansionStaffRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/removeOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/mansionStaffRelationshipIdentifier" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staffMemberIdentifierInRequest" + } + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "removeOperationCode": { + "enum": [ + "remove" + ], + "type": "string" + }, + "residenceIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/buildingIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "residenceIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/buildingIdentifierInResponse" + }, + { + "required": [ + "type" + ], + "type": "object", + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "familyHomes": "#/components/schemas/familyHomeIdentifierInResponse", + "mansions": "#/components/schemas/mansionIdentifierInResponse" + } + } + } + ], + "additionalProperties": false + }, + "resourceInCreateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "bathrooms": "#/components/schemas/dataInCreateBathroomRequest", + "bedrooms": "#/components/schemas/dataInCreateBedroomRequest", + "buildings": "#/components/schemas/dataInCreateBuildingRequest", + "familyHomes": "#/components/schemas/dataInCreateFamilyHomeRequest", + "kitchens": "#/components/schemas/dataInCreateKitchenRequest", + "livingRooms": "#/components/schemas/dataInCreateLivingRoomRequest", + "mansions": "#/components/schemas/dataInCreateMansionRequest", + "residences": "#/components/schemas/dataInCreateResidenceRequest", + "rooms": "#/components/schemas/dataInCreateRoomRequest", + "toilets": "#/components/schemas/dataInCreateToiletRequest" + } + }, + "x-abstract": true + }, + "resourceInResponse": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "bathrooms": "#/components/schemas/dataInBathroomResponse", + "bedrooms": "#/components/schemas/dataInBedroomResponse", + "buildings": "#/components/schemas/dataInBuildingResponse", + "familyHomes": "#/components/schemas/dataInFamilyHomeResponse", + "kitchens": "#/components/schemas/dataInKitchenResponse", + "livingRooms": "#/components/schemas/dataInLivingRoomResponse", + "mansions": "#/components/schemas/dataInMansionResponse", + "residences": "#/components/schemas/dataInResidenceResponse", + "rooms": "#/components/schemas/dataInRoomResponse", + "toilets": "#/components/schemas/dataInToiletResponse" + } + }, + "x-abstract": true + }, + "resourceInUpdateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "buildings": "#/components/schemas/dataInUpdateBuildingRequest", + "familyHomes": "#/components/schemas/dataInUpdateFamilyHomeRequest", + "mansions": "#/components/schemas/dataInUpdateMansionRequest", + "residences": "#/components/schemas/dataInUpdateResidenceRequest" + } + }, + "x-abstract": true + }, + "resourceLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceType": { + "enum": [ + "bathrooms", + "bedrooms", + "buildings", + "familyHomes", + "kitchens", + "livingRooms", + "mansions", + "residences", + "rooms", + "staffMembers", + "toilets" + ], + "type": "string" + }, + "roomIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "roomIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/roomResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "bathrooms": "#/components/schemas/bathroomIdentifierInResponse", + "bedrooms": "#/components/schemas/bedroomIdentifierInResponse", + "kitchens": "#/components/schemas/kitchenIdentifierInResponse", + "livingRooms": "#/components/schemas/livingRoomIdentifierInResponse", + "toilets": "#/components/schemas/toiletIdentifierInResponse" + } + }, + "x-abstract": true + }, + "roomResidenceRelationshipIdentifier": { + "required": [ + "relationship", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/roomResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + }, + "relationship": { + "allOf": [ + { + "$ref": "#/components/schemas/roomResidenceRelationshipName" + } + ] + } + }, + "additionalProperties": false + }, + "roomResidenceRelationshipName": { + "enum": [ + "residence" + ], + "type": "string" + }, + "roomResourceType": { + "enum": [ + "bathrooms", + "bedrooms", + "kitchens", + "livingRooms", + "toilets" + ], + "type": "string" + }, + "staffMemberIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "lid": { + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "staffMemberIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/staffMemberResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "staffMemberResourceType": { + "enum": [ + "staffMembers" + ], + "type": "string" + }, + "toManyRoomInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roomIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyRoomInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roomIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyStaffMemberInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staffMemberIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyStaffMemberInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staffMemberIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneResidenceInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneResidenceInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toiletIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "toiletIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateBathroomResidenceRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/updateRoomResidenceRelationshipOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateBedroomResidenceRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/updateRoomResidenceRelationshipOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateFamilyHomeOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/updateResidenceOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateKitchenResidenceRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/updateRoomResidenceRelationshipOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateLivingRoomResidenceRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/updateRoomResidenceRelationshipOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateMansionOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/updateResidenceOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateOperationCode": { + "enum": [ + "update" + ], + "type": "string" + }, + "updateResidenceOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInRequest" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateResidenceRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateRoomResidenceRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/atomicOperation" + }, + { + "required": [ + "data", + "op", + "ref" + ], + "type": "object", + "properties": { + "op": { + "allOf": [ + { + "$ref": "#/components/schemas/updateOperationCode" + } + ] + }, + "ref": { + "allOf": [ + { + "$ref": "#/components/schemas/roomResidenceRelationshipIdentifier" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateToiletResidenceRelationshipOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/updateRoomResidenceRelationshipOperation" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/test/OpenApiTests/ResourceInheritance/SubsetOfOperations/SubsetOfOperationsEndpointFilter.cs b/test/OpenApiTests/ResourceInheritance/SubsetOfOperations/SubsetOfOperationsEndpointFilter.cs new file mode 100644 index 0000000000..ebeb7e0018 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/SubsetOfOperations/SubsetOfOperationsEndpointFilter.cs @@ -0,0 +1,13 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; + +namespace OpenApiTests.ResourceInheritance.SubsetOfOperations; + +public sealed class SubsetOfOperationsEndpointFilter : IJsonApiEndpointFilter +{ + public bool IsEnabled(ResourceType resourceType, JsonApiEndpoints endpoint) + { + return false; + } +} diff --git a/test/OpenApiTests/ResourceInheritance/SubsetOfOperations/SubsetOfOperationsInheritanceTests.cs b/test/OpenApiTests/ResourceInheritance/SubsetOfOperations/SubsetOfOperationsInheritanceTests.cs new file mode 100644 index 0000000000..7d49d6b2ea --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/SubsetOfOperations/SubsetOfOperationsInheritanceTests.cs @@ -0,0 +1,341 @@ +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; +using Microsoft.Extensions.DependencyInjection; +using OpenApiTests.ResourceInheritance.Models; +using Xunit; +using Xunit.Abstractions; + +#pragma warning disable format + +namespace OpenApiTests.ResourceInheritance.SubsetOfOperations; + +public sealed class SubsetOfOperationsInheritanceTests : ResourceInheritanceTests +{ + public SubsetOfOperationsInheritanceTests(OpenApiTestContext, ResourceInheritanceDbContext> testContext, + ITestOutputHelper testOutputHelper) + : base(testContext, testOutputHelper, true, true) + { + testContext.ConfigureServices(services => + { + services.AddSingleton(); + services.AddSingleton(); + }); + } + + [Theory] + [InlineData(typeof(District), JsonApiEndpoints.None)] + [InlineData(typeof(StaffMember), JsonApiEndpoints.None)] + [InlineData(typeof(Building), JsonApiEndpoints.None)] + [InlineData(typeof(Residence), JsonApiEndpoints.None)] + [InlineData(typeof(FamilyHome), JsonApiEndpoints.None)] + [InlineData(typeof(Mansion), JsonApiEndpoints.None)] + [InlineData(typeof(Room), JsonApiEndpoints.None)] + [InlineData(typeof(Kitchen), JsonApiEndpoints.None)] + [InlineData(typeof(Bedroom), JsonApiEndpoints.None)] + [InlineData(typeof(Bathroom), JsonApiEndpoints.None)] + [InlineData(typeof(LivingRoom), JsonApiEndpoints.None)] + [InlineData(typeof(Toilet), JsonApiEndpoints.None)] + [InlineData(typeof(Road), JsonApiEndpoints.None)] + [InlineData(typeof(CyclePath), JsonApiEndpoints.None)] + public override async Task Only_expected_endpoints_are_exposed(Type resourceClrType, JsonApiEndpoints expected) + { + await base.Only_expected_endpoints_are_exposed(resourceClrType, expected); + } + + [Theory] + [InlineData(true)] + public override async Task Operations_endpoint_is_exposed(bool enabled) + { + await base.Operations_endpoint_is_exposed(enabled); + } + + [Theory] + [InlineData("resourceInCreateRequest", false, "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings")] + [InlineData("resourceInUpdateRequest", false, "familyHomes|mansions|residences|buildings")] + [InlineData("identifierInRequest", false, "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|staffMembers")] + [InlineData("resourceInResponse", false, "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings")] + [InlineData("dataInBuildingResponse", true, "familyHomes|mansions|residences")] + [InlineData("buildingIdentifierInResponse", false, "familyHomes|mansions|residences")] + [InlineData("dataInResidenceResponse", true, "familyHomes|mansions")] + [InlineData("residenceIdentifierInResponse", true, "familyHomes|mansions")] + [InlineData("dataInRoomResponse", true, "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("roomIdentifierInResponse", false, "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("dataInRoadResponse", true, null)] + [InlineData("roadIdentifierInResponse", false, null)] + public override async Task Expected_names_appear_in_type_discriminator_mapping(string schemaName, bool isWrapped, string? discriminatorValues) + { + await base.Expected_names_appear_in_type_discriminator_mapping(schemaName, isWrapped, discriminatorValues); + } + + [Theory] + [InlineData("attributesInCreateRequest", "familyHomes|mansions|residences|buildings|bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms")] + [InlineData("attributesInUpdateRequest", "familyHomes|mansions|residences|buildings")] + [InlineData("relationshipsInCreateRequest", "familyHomes|mansions|residences|buildings|bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms")] + [InlineData("relationshipsInUpdateRequest", "familyHomes|mansions|residences|buildings")] + [InlineData("!attributesInBuildingResponse", "familyHomes|mansions|residences")] + [InlineData("!relationshipsInBuildingResponse", "familyHomes|mansions|residences")] + [InlineData("!attributesInRoomResponse", "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("!relationshipsInRoomResponse", "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("!attributesInRoadResponse", null)] + [InlineData("!relationshipsInRoadResponse", null)] + [InlineData("atomicOperation", + // @formatter:keep_existing_linebreaks true + "" + + "addResidence|updateResidence|" + + "addFamilyHome|updateFamilyHome|addToFamilyHomeRooms|" + + "addMansion|updateMansion|removeFromMansionRooms|removeFromMansionStaff|" + + "addRoom|updateRoomResidence|" + + "addBathroom|updateBathroomResidence|" + + "addBedroom|updateBedroomResidence|" + + "addKitchen|updateKitchenResidence|" + + "addLivingRoom|updateLivingRoomResidence|" + + "addToilet|updateToiletResidence" + + "" + + "" + + "" + + "" + // @formatter:keep_existing_linebreaks restore + )] + public override async Task Expected_names_appear_in_openapi_discriminator_mapping(string schemaName, string? discriminatorValues) + { + await base.Expected_names_appear_in_openapi_discriminator_mapping(schemaName, discriminatorValues); + } + + [Theory] + [InlineData("buildingResourceType", "familyHomes|mansions|residences")] + [InlineData("residenceResourceType", null)] + [InlineData("familyHomeResourceType", "familyHomes")] + [InlineData("mansionResourceType", "mansions")] + [InlineData("roomResourceType", "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("bathroomResourceType", null)] + [InlineData("bedroomResourceType", null)] + [InlineData("kitchenResourceType", null)] + [InlineData("livingRoomResourceType", null)] + [InlineData("toiletResourceType", null)] + [InlineData("roadResourceType", null)] + [InlineData("cyclePathResourceType", null)] + [InlineData("districtResourceType", null)] + [InlineData("staffMemberResourceType", "staffMembers")] + [InlineData("resourceType", "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|staffMembers")] + public override async Task Expected_names_appear_in_resource_type_enum(string schemaName, string? enumValues) + { + await base.Expected_names_appear_in_resource_type_enum(schemaName, enumValues); + } + + [Theory] + [InlineData("resourceInCreateRequest", true, null, "type|meta")] + [InlineData("attributesInCreateRequest", true, null, "openapi:discriminator")] + [InlineData("relationshipsInCreateRequest", true, null, "openapi:discriminator")] + [InlineData("resourceInUpdateRequest", true, null, "type|meta")] + [InlineData("attributesInUpdateRequest", true, null, "openapi:discriminator")] + [InlineData("relationshipsInUpdateRequest", true, null, "openapi:discriminator")] + [InlineData("identifierInRequest", true, null, "type|meta")] + [InlineData("resourceInResponse", true, null, "type|meta")] + [InlineData("atomicOperation", true, null, "openapi:discriminator|meta")] + // Building hierarchy: Resource Data + [InlineData("dataInCreateBuildingRequest", true, "resourceInCreateRequest", "lid|attributes|relationships")] + [InlineData("dataInCreateResidenceRequest", false, "dataInCreateBuildingRequest", null)] + [InlineData("dataInCreateFamilyHomeRequest", false, "dataInCreateResidenceRequest", null)] + [InlineData("dataInCreateMansionRequest", false, "dataInCreateResidenceRequest", null)] + [InlineData("dataInUpdateBuildingRequest", true, "resourceInUpdateRequest", "id|lid|attributes|relationships")] + [InlineData("dataInUpdateResidenceRequest", false, "dataInUpdateBuildingRequest", null)] + [InlineData("dataInUpdateFamilyHomeRequest", false, "dataInUpdateResidenceRequest", null)] + [InlineData("dataInUpdateMansionRequest", false, "dataInUpdateResidenceRequest", null)] + [InlineData("dataInBuildingResponse", true, "resourceInResponse", "id|attributes|relationships|links")] + [InlineData("dataInResidenceResponse", false, "dataInBuildingResponse", null)] + [InlineData("dataInFamilyHomeResponse", false, "dataInResidenceResponse", null)] + [InlineData("dataInMansionResponse", false, "dataInResidenceResponse", null)] + // Building hierarchy: Attributes + [InlineData("attributesInCreateBuildingRequest", true, "attributesInCreateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInCreateResidenceRequest", false, "attributesInCreateBuildingRequest", "numberOfResidents")] + [InlineData("attributesInCreateFamilyHomeRequest", false, "attributesInCreateResidenceRequest", "floorCount")] + [InlineData("attributesInCreateMansionRequest", false, "attributesInCreateResidenceRequest", "ownerName")] + [InlineData("attributesInUpdateBuildingRequest", true, "attributesInUpdateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInUpdateResidenceRequest", false, "attributesInUpdateBuildingRequest", "numberOfResidents")] + [InlineData("attributesInUpdateFamilyHomeRequest", false, "attributesInUpdateResidenceRequest", "floorCount")] + [InlineData("attributesInUpdateMansionRequest", false, "attributesInUpdateResidenceRequest", "ownerName")] + [InlineData("attributesInBuildingResponse", true, "attributesInResponse", "surfaceInSquareMeters")] + [InlineData("attributesInResidenceResponse", false, "attributesInBuildingResponse", "numberOfResidents")] + [InlineData("attributesInFamilyHomeResponse", false, "attributesInResidenceResponse", "floorCount")] + [InlineData("attributesInMansionResponse", false, "attributesInResidenceResponse", "ownerName")] + // Building hierarchy: Relationships + [InlineData("relationshipsInCreateBuildingRequest", true, "relationshipsInCreateRequest", null)] + [InlineData("relationshipsInCreateResidenceRequest", false, "relationshipsInCreateBuildingRequest", "rooms")] + [InlineData("relationshipsInCreateFamilyHomeRequest", false, "relationshipsInCreateResidenceRequest", null)] + [InlineData("relationshipsInCreateMansionRequest", false, "relationshipsInCreateResidenceRequest", "staff")] + [InlineData("relationshipsInUpdateBuildingRequest", true, "relationshipsInUpdateRequest", null)] + [InlineData("relationshipsInUpdateResidenceRequest", false, "relationshipsInUpdateBuildingRequest", "rooms")] + [InlineData("relationshipsInUpdateFamilyHomeRequest", false, "relationshipsInUpdateResidenceRequest", null)] + [InlineData("relationshipsInUpdateMansionRequest", false, "relationshipsInUpdateResidenceRequest", "staff")] + [InlineData("relationshipsInBuildingResponse", true, "relationshipsInResponse", null)] + [InlineData("relationshipsInResidenceResponse", false, "relationshipsInBuildingResponse", "rooms")] + [InlineData("relationshipsInFamilyHomeResponse", false, "relationshipsInResidenceResponse", null)] + [InlineData("relationshipsInMansionResponse", false, "relationshipsInResidenceResponse", "staff")] + // Building hierarchy: Resource Identifiers + [InlineData("buildingIdentifierInRequest", false, "identifierInRequest", "id|lid")] + [InlineData("residenceIdentifierInRequest", false, "buildingIdentifierInRequest", null)] + [InlineData("familyHomeIdentifierInRequest", false, "residenceIdentifierInRequest", null)] + [InlineData("mansionIdentifierInRequest", false, "residenceIdentifierInRequest", null)] + [InlineData("buildingIdentifierInResponse", true, null, "type|id|meta")] + [InlineData("residenceIdentifierInResponse", false, "buildingIdentifierInResponse", null)] + [InlineData("familyHomeIdentifierInResponse", false, "residenceIdentifierInResponse", null)] + [InlineData("mansionIdentifierInResponse", false, "residenceIdentifierInResponse", null)] + // Building hierarchy: Atomic Operations + [InlineData("createBuildingOperation", false, null, null)] + [InlineData("createResidenceOperation", false, "atomicOperation", "op|data")] + [InlineData("createFamilyHomeOperation", false, "createResidenceOperation", null)] + [InlineData("createMansionOperation", false, "createResidenceOperation", null)] + [InlineData("updateBuildingOperation", false, null, null)] + [InlineData("updateResidenceOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateFamilyHomeOperation", false, "updateResidenceOperation", null)] + [InlineData("updateMansionOperation", false, "updateResidenceOperation", null)] + [InlineData("deleteBuildingOperation", false, null, null)] + [InlineData("deleteResidenceOperation", false, null, null)] + [InlineData("deleteFamilyHomeOperation", false, null, null)] + [InlineData("deleteMansionOperation", false, null, null)] + [InlineData("updateResidenceRoomsRelationshipOperation", false, null, null)] + [InlineData("updateFamilyHomeRoomsRelationshipOperation", false, null, null)] + [InlineData("updateMansionRoomsRelationshipOperation", false, null, null)] + [InlineData("updateMansionStaffRelationshipOperation", false, null, null)] + [InlineData("addToResidenceRoomsRelationshipOperation", false, null, null)] + [InlineData("addToFamilyHomeRoomsRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("addToMansionRoomsRelationshipOperation", false, null, null)] + [InlineData("addToMansionStaffRelationshipOperation", false, null, null)] + [InlineData("removeFromResidenceRoomsRelationshipOperation", false, null, null)] + [InlineData("removeFromFamilyHomeRoomsRelationshipOperation", false, null, null)] + [InlineData("removeFromMansionRoomsRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("removeFromMansionStaffRelationshipOperation", false, "atomicOperation", "op|ref|data")] + // Room hierarchy: Resource Data + [InlineData("dataInCreateRoomRequest", true, "resourceInCreateRequest", "lid|attributes|relationships")] + [InlineData("dataInCreateBathroomRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateBedroomRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateKitchenRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateLivingRoomRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInCreateToiletRequest", false, "dataInCreateRoomRequest", null)] + [InlineData("dataInUpdateRoomRequest", true, null, null)] + [InlineData("dataInUpdateBathroomRequest", false, null, null)] + [InlineData("dataInUpdateBedroomRequest", false, null, null)] + [InlineData("dataInUpdateKitchenRequest", false, null, null)] + [InlineData("dataInUpdateLivingRoomRequest", false, null, null)] + [InlineData("dataInUpdateToiletRequest", false, null, null)] + [InlineData("dataInRoomResponse", true, "resourceInResponse", "id|attributes|relationships|links")] + [InlineData("dataInBathroomResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInBedroomResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInKitchenResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInLivingRoomResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInToiletResponse", false, "dataInRoomResponse", null)] + // Room hierarchy: Attributes + [InlineData("attributesInCreateRoomRequest", true, "attributesInCreateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInCreateBathroomRequest", false, "attributesInCreateRoomRequest", "hasBath")] + [InlineData("attributesInCreateBedroomRequest", false, "attributesInCreateRoomRequest", "bedCount")] + [InlineData("attributesInCreateKitchenRequest", false, "attributesInCreateRoomRequest", "hasPantry")] + [InlineData("attributesInCreateLivingRoomRequest", false, "attributesInCreateRoomRequest", "hasDiningTable")] + [InlineData("attributesInCreateToiletRequest", false, "attributesInCreateRoomRequest", "hasSink")] + [InlineData("attributesInUpdateRoomRequest", true, null, null)] + [InlineData("attributesInUpdateBathroomRequest", false, null, null)] + [InlineData("attributesInUpdateBedroomRequest", false, null, null)] + [InlineData("attributesInUpdateKitchenRequest", false, null, null)] + [InlineData("attributesInUpdateLivingRoomRequest", false, null, null)] + [InlineData("attributesInUpdateToiletRequest", false, null, null)] + [InlineData("attributesInRoomResponse", true, "attributesInResponse", "surfaceInSquareMeters")] + [InlineData("attributesInBathroomResponse", false, "attributesInRoomResponse", "hasBath")] + [InlineData("attributesInBedroomResponse", false, "attributesInRoomResponse", "bedCount")] + [InlineData("attributesInKitchenResponse", false, "attributesInRoomResponse", "hasPantry")] + [InlineData("attributesInLivingRoomResponse", false, "attributesInRoomResponse", "hasDiningTable")] + [InlineData("attributesInToiletResponse", false, "attributesInRoomResponse", "hasSink")] + // Room hierarchy: Relationships + [InlineData("relationshipsInCreateRoomRequest", true, "relationshipsInCreateRequest", "residence")] + [InlineData("relationshipsInCreateBathroomRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateBedroomRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateKitchenRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateLivingRoomRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInCreateToiletRequest", false, "relationshipsInCreateRoomRequest", null)] + [InlineData("relationshipsInUpdateRoomRequest", true, null, null)] + [InlineData("relationshipsInUpdateBathroomRequest", false, null, null)] + [InlineData("relationshipsInUpdateBedroomRequest", false, null, null)] + [InlineData("relationshipsInUpdateKitchenRequest", false, null, null)] + [InlineData("relationshipsInUpdateLivingRoomRequest", false, null, null)] + [InlineData("relationshipsInUpdateToiletRequest", false, null, null)] + [InlineData("relationshipsInRoomResponse", true, "relationshipsInResponse", "residence")] + [InlineData("relationshipsInBathroomResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInBedroomResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInKitchenResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInLivingRoomResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInToiletResponse", false, "relationshipsInRoomResponse", null)] + // Room hierarchy: Resource Identifiers + [InlineData("roomIdentifierInRequest", false, "identifierInRequest", "id|lid")] + [InlineData("bathroomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("bedroomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("kitchenIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("livingRoomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("toiletIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("roomIdentifierInResponse", true, null, "type|id|meta")] + [InlineData("bathroomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("bedroomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("kitchenIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("livingRoomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("toiletIdentifierInResponse", false, "roomIdentifierInResponse", null)] + // Room hierarchy: Atomic Operations + [InlineData("createRoomOperation", false, "atomicOperation", "op|data")] + [InlineData("createBathroomOperation", false, "createRoomOperation", null)] + [InlineData("createBedroomOperation", false, "createRoomOperation", null)] + [InlineData("createKitchenOperation", false, "createRoomOperation", null)] + [InlineData("createLivingRoomOperation", false, "createRoomOperation", null)] + [InlineData("createToiletOperation", false, "createRoomOperation", null)] + [InlineData("updateRoomOperation", false, null, null)] + [InlineData("updateBathroomOperation", false, null, null)] + [InlineData("updateBedroomOperation", false, null, null)] + [InlineData("updateKitchenOperation", false, null, null)] + [InlineData("updateLivingRoomOperation", false, null, null)] + [InlineData("updateToiletOperation", false, null, null)] + [InlineData("deleteRoomOperation", false, null, null)] + [InlineData("deleteBathroomOperation", false, null, null)] + [InlineData("deleteBedroomOperation", false, null, null)] + [InlineData("deleteKitchenOperation", false, null, null)] + [InlineData("deleteLivingRoomOperation", false, null, null)] + [InlineData("deleteToiletOperation", false, null, null)] + [InlineData("updateRoomResidenceRelationshipOperation", false, "atomicOperation", "op|ref|data")] + [InlineData("updateBathroomResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + [InlineData("updateBedroomResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + [InlineData("updateKitchenResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + [InlineData("updateLivingRoomResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + [InlineData("updateToiletResidenceRelationshipOperation", false, "updateRoomResidenceRelationshipOperation", null)] + // Road hierarchy: Resource Data + [InlineData("dataInCreateRoadRequest", false, null, null)] + [InlineData("dataInCreateCyclePathRequest", false, null, null)] + [InlineData("dataInUpdateRoadRequest", false, null, null)] + [InlineData("dataInUpdateCyclePathRequest", false, null, null)] + [InlineData("dataInRoadResponse", false, null, null)] + [InlineData("dataInCyclePathResponse", false, null, null)] + // Road hierarchy: Attributes + [InlineData("attributesInCreateRoadRequest", false, null, null)] + [InlineData("attributesInCreateCyclePathRequest", false, null, null)] + [InlineData("attributesInUpdateRoadRequest", false, null, null)] + [InlineData("attributesInUpdateCyclePathRequest", false, null, null)] + [InlineData("attributesInRoadResponse", false, null, null)] + [InlineData("attributesInCyclePathResponse", false, null, null)] + // Road hierarchy: Relationships + [InlineData("relationshipsInCreateRoadRequest", false, null, null)] + [InlineData("relationshipsInCreateCyclePathRequest", false, null, null)] + [InlineData("relationshipsInUpdateRoadRequest", false, null, null)] + [InlineData("relationshipsInUpdateCyclePathRequest", false, null, null)] + [InlineData("relationshipsInRoadResponse", false, null, null)] + [InlineData("relationshipsInCyclePathResponse", false, null, null)] + // Road hierarchy: Resource Identifiers + [InlineData("roadIdentifierInRequest", false, null, null)] + [InlineData("cyclePathIdentifierInRequest", false, null, null)] + [InlineData("roadIdentifierInResponse", false, null, null)] + [InlineData("cyclePathIdentifierInResponse", false, null, null)] + // Road hierarchy: Atomic Operations + [InlineData("createRoadOperation", false, null, null)] + [InlineData("createCyclePathOperation", false, null, null)] + [InlineData("updateRoadOperation", false, null, null)] + [InlineData("updateCyclePathOperation", false, null, null)] + [InlineData("deleteRoadOperation", false, null, null)] + [InlineData("deleteCyclePathOperation", false, null, null)] + public override async Task Component_schemas_have_expected_base_type(string schemaName, bool isAbstract, string? baseType, string? properties) + { + await base.Component_schemas_have_expected_base_type(schemaName, isAbstract, baseType, properties); + } +} diff --git a/test/OpenApiTests/ResourceInheritance/SubsetOfOperations/SubsetOfOperationsOperationFilter.cs b/test/OpenApiTests/ResourceInheritance/SubsetOfOperations/SubsetOfOperationsOperationFilter.cs new file mode 100644 index 0000000000..0636b46e47 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/SubsetOfOperations/SubsetOfOperationsOperationFilter.cs @@ -0,0 +1,36 @@ +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using OpenApiTests.ResourceInheritance.Models; + +namespace OpenApiTests.ResourceInheritance.SubsetOfOperations; + +public sealed class SubsetOfOperationsOperationFilter : DefaultOperationFilter +{ + protected override JsonApiEndpoints? GetJsonApiEndpoints(ResourceType resourceType) + { + Type resourceClrType = resourceType.ClrType; + + if (resourceClrType == typeof(Residence)) + { + return JsonApiEndpoints.Post | JsonApiEndpoints.Patch; + } + + if (resourceClrType == typeof(FamilyHome)) + { + return JsonApiEndpoints.GetRelationship | JsonApiEndpoints.PostRelationship; + } + + if (resourceClrType == typeof(Mansion)) + { + return JsonApiEndpoints.DeleteRelationship; + } + + if (resourceClrType == typeof(Room)) + { + return JsonApiEndpoints.Post | JsonApiEndpoints.PatchRelationship; + } + + return JsonApiEndpoints.None; + } +} diff --git a/test/OpenApiTests/ResourceInheritance/SubsetOfVarious/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/ResourceInheritance/SubsetOfVarious/GeneratedSwagger/swagger.g.json new file mode 100644 index 0000000000..42301a5d4d --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/SubsetOfVarious/GeneratedSwagger/swagger.g.json @@ -0,0 +1,3369 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "OpenApiTests", + "version": "1.0" + }, + "servers": [ + { + "url": "http://localhost" + } + ], + "paths": { + "/buildings": { + "post": { + "tags": [ + "buildings" + ], + "summary": "Creates a new building.", + "operationId": "postBuilding", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the building to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createBuildingRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The building was successfully created, which resulted in additional changes. The newly created building is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created building can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryBuildingResponseDocument" + } + } + } + }, + "204": { + "description": "The building was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/buildings/{id}": { + "patch": { + "tags": [ + "buildings" + ], + "summary": "Updates an existing building.", + "operationId": "patchBuilding", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the building to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the building to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateBuildingRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The building was successfully updated, which resulted in additional changes. The updated building is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryBuildingResponseDocument" + } + } + } + }, + "204": { + "description": "The building was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The building or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/cyclePaths/{id}": { + "get": { + "tags": [ + "cyclePaths" + ], + "summary": "Retrieves an individual cyclePath by its identifier.", + "operationId": "getCyclePath", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the cyclePath to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found cyclePath.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryCyclePathResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The cyclePath does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "cyclePaths" + ], + "summary": "Retrieves an individual cyclePath by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headCyclePath", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the cyclePath to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The cyclePath does not exist." + } + } + } + }, + "/districts": { + "get": { + "tags": [ + "districts" + ], + "summary": "Retrieves a collection of districts.", + "operationId": "getDistrictCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found districts, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/districtCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "districts" + ], + "summary": "Retrieves a collection of districts without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headDistrictCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + } + }, + "/familyHomes/{id}/relationships/rooms": { + "get": { + "tags": [ + "familyHomes" + ], + "summary": "Retrieves the related room identities of an individual familyHome's rooms relationship.", + "operationId": "getFamilyHomeRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the familyHome whose related room identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found room identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/roomIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The familyHome does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "familyHomes" + ], + "summary": "Retrieves the related room identities of an individual familyHome's rooms relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headFamilyHomeRoomsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the familyHome whose related room identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The familyHome does not exist." + } + } + } + } + }, + "components": { + "schemas": { + "attributesInBathroomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInRoomResponse" + }, + { + "type": "object", + "properties": { + "hasBath": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInBedroomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInRoomResponse" + }, + { + "type": "object", + "properties": { + "bedCount": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInBuildingResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "surfaceInSquareMeters": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "familyHomes": "#/components/schemas/attributesInFamilyHomeResponse", + "mansions": "#/components/schemas/attributesInMansionResponse", + "residences": "#/components/schemas/attributesInResidenceResponse" + } + }, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "attributesInCreateBuildingRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "required": [ + "surfaceInSquareMeters" + ], + "type": "object", + "properties": { + "surfaceInSquareMeters": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "attributesInCreateFamilyHomeRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateResidenceRequest" + }, + { + "type": "object", + "properties": { + "floorCount": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateMansionRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateResidenceRequest" + }, + { + "required": [ + "ownerName" + ], + "type": "object", + "properties": { + "ownerName": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "buildings": "#/components/schemas/attributesInCreateBuildingRequest", + "familyHomes": "#/components/schemas/attributesInCreateFamilyHomeRequest", + "mansions": "#/components/schemas/attributesInCreateMansionRequest", + "residences": "#/components/schemas/attributesInCreateResidenceRequest" + } + }, + "x-abstract": true + }, + "attributesInCreateResidenceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateBuildingRequest" + }, + { + "required": [ + "numberOfResidents" + ], + "type": "object", + "properties": { + "numberOfResidents": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInCyclePathResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInRoadResponse" + }, + { + "type": "object", + "properties": { + "hasLaneForPedestrians": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInDistrictResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInFamilyHomeResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResidenceResponse" + }, + { + "type": "object", + "properties": { + "floorCount": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInKitchenResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInRoomResponse" + }, + { + "type": "object", + "properties": { + "hasPantry": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInLivingRoomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInRoomResponse" + }, + { + "type": "object", + "properties": { + "hasDiningTable": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInMansionResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResidenceResponse" + }, + { + "type": "object", + "properties": { + "ownerName": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInResidenceResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInBuildingResponse" + }, + { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "numberOfResidents": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "familyHomes": "#/components/schemas/attributesInFamilyHomeResponse", + "mansions": "#/components/schemas/attributesInMansionResponse" + } + } + } + ], + "additionalProperties": false + }, + "attributesInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "bathrooms": "#/components/schemas/attributesInBathroomResponse", + "bedrooms": "#/components/schemas/attributesInBedroomResponse", + "buildings": "#/components/schemas/attributesInBuildingResponse", + "cyclePaths": "#/components/schemas/attributesInCyclePathResponse", + "districts": "#/components/schemas/attributesInDistrictResponse", + "familyHomes": "#/components/schemas/attributesInFamilyHomeResponse", + "kitchens": "#/components/schemas/attributesInKitchenResponse", + "livingRooms": "#/components/schemas/attributesInLivingRoomResponse", + "mansions": "#/components/schemas/attributesInMansionResponse", + "residences": "#/components/schemas/attributesInResidenceResponse", + "roads": "#/components/schemas/attributesInRoadResponse", + "rooms": "#/components/schemas/attributesInRoomResponse", + "staffMembers": "#/components/schemas/attributesInStaffMemberResponse", + "toilets": "#/components/schemas/attributesInToiletResponse" + } + }, + "x-abstract": true + }, + "attributesInRoadResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "lengthInMeters": { + "type": "number", + "format": "double" + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "cyclePaths": "#/components/schemas/attributesInCyclePathResponse" + } + } + } + ], + "additionalProperties": false + }, + "attributesInRoomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "surfaceInSquareMeters": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "bathrooms": "#/components/schemas/attributesInBathroomResponse", + "bedrooms": "#/components/schemas/attributesInBedroomResponse", + "kitchens": "#/components/schemas/attributesInKitchenResponse", + "livingRooms": "#/components/schemas/attributesInLivingRoomResponse", + "toilets": "#/components/schemas/attributesInToiletResponse" + } + }, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "attributesInStaffMemberResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInToiletResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInRoomResponse" + }, + { + "type": "object", + "properties": { + "hasSink": { + "type": "boolean" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateBuildingRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "surfaceInSquareMeters": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "attributesInUpdateFamilyHomeRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateResidenceRequest" + }, + { + "type": "object", + "properties": { + "floorCount": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateMansionRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateResidenceRequest" + }, + { + "type": "object", + "properties": { + "ownerName": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "buildings": "#/components/schemas/attributesInUpdateBuildingRequest", + "familyHomes": "#/components/schemas/attributesInUpdateFamilyHomeRequest", + "mansions": "#/components/schemas/attributesInUpdateMansionRequest", + "residences": "#/components/schemas/attributesInUpdateResidenceRequest" + } + }, + "x-abstract": true + }, + "attributesInUpdateResidenceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateBuildingRequest" + }, + { + "type": "object", + "properties": { + "numberOfResidents": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "bathroomIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "bathroomIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "bedroomIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "bedroomIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "buildingIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/buildingResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "familyHomes": "#/components/schemas/familyHomeIdentifierInResponse", + "mansions": "#/components/schemas/mansionIdentifierInResponse", + "residences": "#/components/schemas/residenceIdentifierInResponse" + } + }, + "x-abstract": true + }, + "buildingResourceType": { + "enum": [ + "familyHomes", + "mansions", + "residences" + ], + "type": "string" + }, + "createBuildingRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateBuildingRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "cyclePathIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/roadIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInBathroomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInBedroomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInBuildingResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInBuildingResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInBuildingResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "familyHomes": "#/components/schemas/dataInFamilyHomeResponse", + "mansions": "#/components/schemas/dataInMansionResponse", + "residences": "#/components/schemas/dataInResidenceResponse" + } + }, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "dataInCreateBuildingRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateBuildingRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateBuildingRequest" + } + ] + } + }, + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "dataInCreateFamilyHomeRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateResidenceRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateMansionRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateResidenceRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCreateResidenceRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateBuildingRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInCyclePathResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInRoadResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInDistrictResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "uuid" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInDistrictResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInDistrictResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInFamilyHomeResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInResidenceResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInKitchenResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInLivingRoomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInMansionResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInResidenceResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInResidenceResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInBuildingResponse" + }, + { + "required": [ + "type" + ], + "type": "object", + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "familyHomes": "#/components/schemas/dataInFamilyHomeResponse", + "mansions": "#/components/schemas/dataInMansionResponse" + } + } + } + ], + "additionalProperties": false + }, + "dataInRoadResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInRoadResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInRoadResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "cyclePaths": "#/components/schemas/dataInCyclePathResponse" + } + } + } + ], + "additionalProperties": false + }, + "dataInRoomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInRoomResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInRoomResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "bathrooms": "#/components/schemas/dataInBathroomResponse", + "bedrooms": "#/components/schemas/dataInBedroomResponse", + "kitchens": "#/components/schemas/dataInKitchenResponse", + "livingRooms": "#/components/schemas/dataInLivingRoomResponse", + "toilets": "#/components/schemas/dataInToiletResponse" + } + }, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "dataInStaffMemberResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInStaffMemberResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInToiletResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateBuildingRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateBuildingRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateBuildingRequest" + } + ] + } + }, + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "dataInUpdateFamilyHomeRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateResidenceRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateMansionRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateResidenceRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateResidenceRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateBuildingRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "districtCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInDistrictResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorLinks": { + "type": "object", + "properties": { + "about": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorObject": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorLinks" + } + ], + "nullable": true + }, + "status": { + "type": "string" + }, + "code": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/errorSource" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorResponseDocument": { + "required": [ + "errors", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorTopLevelLinks" + } + ] + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/errorObject" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorSource": { + "type": "object", + "properties": { + "pointer": { + "type": "string", + "nullable": true + }, + "parameter": { + "type": "string", + "nullable": true + }, + "header": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "familyHomeIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "identifierInRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "bathrooms": "#/components/schemas/bathroomIdentifierInRequest", + "bedrooms": "#/components/schemas/bedroomIdentifierInRequest", + "kitchens": "#/components/schemas/kitchenIdentifierInRequest", + "livingRooms": "#/components/schemas/livingRoomIdentifierInRequest", + "rooms": "#/components/schemas/roomIdentifierInRequest", + "staffMembers": "#/components/schemas/staffMemberIdentifierInRequest", + "toilets": "#/components/schemas/toiletIdentifierInRequest" + } + }, + "x-abstract": true + }, + "kitchenIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "kitchenIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "livingRoomIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "livingRoomIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "mansionIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "meta": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "primaryBuildingResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInBuildingResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryCyclePathResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCyclePathResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "relationshipLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + } + }, + "additionalProperties": false + }, + "relationshipsInBathroomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInBedroomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInBuildingResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "familyHomes": "#/components/schemas/relationshipsInFamilyHomeResponse", + "mansions": "#/components/schemas/relationshipsInMansionResponse", + "residences": "#/components/schemas/relationshipsInResidenceResponse" + } + }, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "relationshipsInCreateBuildingRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "type": "object", + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "relationshipsInCreateFamilyHomeRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateResidenceRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateMansionRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateResidenceRequest" + }, + { + "type": "object", + "properties": { + "staff": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStaffMemberInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "buildings": "#/components/schemas/relationshipsInCreateBuildingRequest", + "familyHomes": "#/components/schemas/relationshipsInCreateFamilyHomeRequest", + "mansions": "#/components/schemas/relationshipsInCreateMansionRequest", + "residences": "#/components/schemas/relationshipsInCreateResidenceRequest" + } + }, + "x-abstract": true + }, + "relationshipsInCreateResidenceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateBuildingRequest" + }, + { + "type": "object", + "properties": { + "rooms": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInCyclePathResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInRoadResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInDistrictResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "type": "object", + "properties": { + "buildings": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyBuildingInResponse" + } + ] + }, + "roads": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoadInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInFamilyHomeResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResidenceResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInKitchenResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInLivingRoomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInMansionResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResidenceResponse" + }, + { + "type": "object", + "properties": { + "staff": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStaffMemberInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInResidenceResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInBuildingResponse" + }, + { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "rooms": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInResponse" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "familyHomes": "#/components/schemas/relationshipsInFamilyHomeResponse", + "mansions": "#/components/schemas/relationshipsInMansionResponse" + } + } + } + ], + "additionalProperties": false + }, + "relationshipsInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "bathrooms": "#/components/schemas/relationshipsInBathroomResponse", + "bedrooms": "#/components/schemas/relationshipsInBedroomResponse", + "buildings": "#/components/schemas/relationshipsInBuildingResponse", + "cyclePaths": "#/components/schemas/relationshipsInCyclePathResponse", + "districts": "#/components/schemas/relationshipsInDistrictResponse", + "familyHomes": "#/components/schemas/relationshipsInFamilyHomeResponse", + "kitchens": "#/components/schemas/relationshipsInKitchenResponse", + "livingRooms": "#/components/schemas/relationshipsInLivingRoomResponse", + "mansions": "#/components/schemas/relationshipsInMansionResponse", + "residences": "#/components/schemas/relationshipsInResidenceResponse", + "roads": "#/components/schemas/relationshipsInRoadResponse", + "rooms": "#/components/schemas/relationshipsInRoomResponse", + "toilets": "#/components/schemas/relationshipsInToiletResponse" + } + }, + "x-abstract": true + }, + "relationshipsInRoadResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "cyclePaths": "#/components/schemas/relationshipsInCyclePathResponse" + } + } + } + ], + "additionalProperties": false + }, + "relationshipsInRoomResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "residence": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneResidenceInResponse" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "bathrooms": "#/components/schemas/relationshipsInBathroomResponse", + "bedrooms": "#/components/schemas/relationshipsInBedroomResponse", + "kitchens": "#/components/schemas/relationshipsInKitchenResponse", + "livingRooms": "#/components/schemas/relationshipsInLivingRoomResponse", + "toilets": "#/components/schemas/relationshipsInToiletResponse" + } + }, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "relationshipsInToiletResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInRoomResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateBuildingRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "additionalProperties": false, + "x-abstract": true + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateFamilyHomeRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateResidenceRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateMansionRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateResidenceRequest" + }, + { + "type": "object", + "properties": { + "staff": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyStaffMemberInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "buildings": "#/components/schemas/relationshipsInUpdateBuildingRequest", + "familyHomes": "#/components/schemas/relationshipsInUpdateFamilyHomeRequest", + "mansions": "#/components/schemas/relationshipsInUpdateMansionRequest", + "residences": "#/components/schemas/relationshipsInUpdateResidenceRequest" + } + }, + "x-abstract": true + }, + "relationshipsInUpdateResidenceRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateBuildingRequest" + }, + { + "type": "object", + "properties": { + "rooms": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyRoomInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "residenceIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/buildingIdentifierInResponse" + }, + { + "required": [ + "type" + ], + "type": "object", + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "familyHomes": "#/components/schemas/familyHomeIdentifierInResponse", + "mansions": "#/components/schemas/mansionIdentifierInResponse" + } + } + } + ], + "additionalProperties": false + }, + "resourceCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceIdentifierCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceInCreateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "buildings": "#/components/schemas/dataInCreateBuildingRequest", + "familyHomes": "#/components/schemas/dataInCreateFamilyHomeRequest", + "mansions": "#/components/schemas/dataInCreateMansionRequest", + "residences": "#/components/schemas/dataInCreateResidenceRequest" + } + }, + "x-abstract": true + }, + "resourceInResponse": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "bathrooms": "#/components/schemas/dataInBathroomResponse", + "bedrooms": "#/components/schemas/dataInBedroomResponse", + "buildings": "#/components/schemas/dataInBuildingResponse", + "cyclePaths": "#/components/schemas/dataInCyclePathResponse", + "districts": "#/components/schemas/dataInDistrictResponse", + "familyHomes": "#/components/schemas/dataInFamilyHomeResponse", + "kitchens": "#/components/schemas/dataInKitchenResponse", + "livingRooms": "#/components/schemas/dataInLivingRoomResponse", + "mansions": "#/components/schemas/dataInMansionResponse", + "residences": "#/components/schemas/dataInResidenceResponse", + "roads": "#/components/schemas/dataInRoadResponse", + "rooms": "#/components/schemas/dataInRoomResponse", + "staffMembers": "#/components/schemas/dataInStaffMemberResponse", + "toilets": "#/components/schemas/dataInToiletResponse" + } + }, + "x-abstract": true + }, + "resourceInUpdateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "buildings": "#/components/schemas/dataInUpdateBuildingRequest", + "familyHomes": "#/components/schemas/dataInUpdateFamilyHomeRequest", + "mansions": "#/components/schemas/dataInUpdateMansionRequest", + "residences": "#/components/schemas/dataInUpdateResidenceRequest" + } + }, + "x-abstract": true + }, + "resourceLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceType": { + "enum": [ + "bathrooms", + "bedrooms", + "buildings", + "cyclePaths", + "districts", + "familyHomes", + "kitchens", + "livingRooms", + "mansions", + "residences", + "roads", + "rooms", + "staffMembers", + "toilets" + ], + "type": "string" + }, + "roadIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/roadResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "cyclePaths": "#/components/schemas/cyclePathIdentifierInResponse" + } + } + }, + "roadResourceType": { + "enum": [ + "cyclePaths", + "roads" + ], + "type": "string" + }, + "roomIdentifierCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roomIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "roomIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "roomIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/roomResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "bathrooms": "#/components/schemas/bathroomIdentifierInResponse", + "bedrooms": "#/components/schemas/bedroomIdentifierInResponse", + "kitchens": "#/components/schemas/kitchenIdentifierInResponse", + "livingRooms": "#/components/schemas/livingRoomIdentifierInResponse", + "toilets": "#/components/schemas/toiletIdentifierInResponse" + } + }, + "x-abstract": true + }, + "roomResourceType": { + "enum": [ + "bathrooms", + "bedrooms", + "kitchens", + "livingRooms", + "toilets" + ], + "type": "string" + }, + "staffMemberIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "staffMemberIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/staffMemberResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "staffMemberResourceType": { + "enum": [ + "staffMembers" + ], + "type": "string" + }, + "toManyBuildingInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/buildingIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyRoadInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roadIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyRoomInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roomIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyRoomInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roomIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyStaffMemberInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staffMemberIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyStaffMemberInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/staffMemberIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneResidenceInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/residenceIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toiletIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInRequest" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "toiletIdentifierInResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/roomIdentifierInResponse" + }, + { + "type": "object", + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "updateBuildingRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateBuildingRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/test/OpenApiTests/ResourceInheritance/SubsetOfVarious/SubsetOfVariousEndpointFilter.cs b/test/OpenApiTests/ResourceInheritance/SubsetOfVarious/SubsetOfVariousEndpointFilter.cs new file mode 100644 index 0000000000..1675f08197 --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/SubsetOfVarious/SubsetOfVariousEndpointFilter.cs @@ -0,0 +1,21 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; +using OpenApiTests.ResourceInheritance.Models; + +namespace OpenApiTests.ResourceInheritance.SubsetOfVarious; + +public sealed class SubsetOfVariousEndpointFilter : IJsonApiEndpointFilter +{ + public bool IsEnabled(ResourceType resourceType, JsonApiEndpoints endpoint) + { + return resourceType.ClrType.Name switch + { + nameof(District) => endpoint == JsonApiEndpoints.GetCollection, + nameof(Building) => endpoint is JsonApiEndpoints.Post or JsonApiEndpoints.Patch, + nameof(FamilyHome) => endpoint is JsonApiEndpoints.GetRelationship, + nameof(CyclePath) => endpoint is JsonApiEndpoints.GetSingle, + _ => false + }; + } +} diff --git a/test/OpenApiTests/ResourceInheritance/SubsetOfVarious/SubsetOfVariousInheritanceTests.cs b/test/OpenApiTests/ResourceInheritance/SubsetOfVarious/SubsetOfVariousInheritanceTests.cs new file mode 100644 index 0000000000..24de06c72a --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/SubsetOfVarious/SubsetOfVariousInheritanceTests.cs @@ -0,0 +1,324 @@ +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Middleware; +using Microsoft.Extensions.DependencyInjection; +using OpenApiTests.ResourceInheritance.Models; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.ResourceInheritance.SubsetOfVarious; + +public sealed class SubsetOfVariousInheritanceTests : ResourceInheritanceTests +{ + public SubsetOfVariousInheritanceTests(OpenApiTestContext, ResourceInheritanceDbContext> testContext, + ITestOutputHelper testOutputHelper) + : base(testContext, testOutputHelper, false, true) + { + testContext.ConfigureServices(services => + { + services.AddSingleton(); + services.AddSingleton(); + }); + } + + [Theory] + [InlineData(typeof(District), JsonApiEndpoints.GetCollection)] + [InlineData(typeof(StaffMember), JsonApiEndpoints.None)] + [InlineData(typeof(Building), JsonApiEndpoints.Post | JsonApiEndpoints.Patch)] + [InlineData(typeof(Residence), JsonApiEndpoints.None)] + [InlineData(typeof(FamilyHome), JsonApiEndpoints.GetRelationship)] + [InlineData(typeof(Mansion), JsonApiEndpoints.None)] + [InlineData(typeof(Room), JsonApiEndpoints.None)] + [InlineData(typeof(Kitchen), JsonApiEndpoints.None)] + [InlineData(typeof(Bedroom), JsonApiEndpoints.None)] + [InlineData(typeof(Bathroom), JsonApiEndpoints.None)] + [InlineData(typeof(LivingRoom), JsonApiEndpoints.None)] + [InlineData(typeof(Toilet), JsonApiEndpoints.None)] + [InlineData(typeof(Road), JsonApiEndpoints.None)] + [InlineData(typeof(CyclePath), JsonApiEndpoints.GetSingle)] + public override async Task Only_expected_endpoints_are_exposed(Type resourceClrType, JsonApiEndpoints expected) + { + await base.Only_expected_endpoints_are_exposed(resourceClrType, expected); + } + + [Theory] + [InlineData(false)] + public override async Task Operations_endpoint_is_exposed(bool enabled) + { + await base.Operations_endpoint_is_exposed(enabled); + } + + [Theory] + [InlineData("resourceInCreateRequest", false, "familyHomes|mansions|residences|buildings")] + [InlineData("resourceInUpdateRequest", false, "familyHomes|mansions|residences|buildings")] + [InlineData("identifierInRequest", false, "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|staffMembers")] + [InlineData("resourceInResponse", false, + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|districts|roads|cyclePaths|staffMembers")] + [InlineData("dataInBuildingResponse", true, "familyHomes|mansions|residences")] + [InlineData("buildingIdentifierInResponse", false, "familyHomes|mansions|residences")] + [InlineData("dataInResidenceResponse", true, "familyHomes|mansions")] + [InlineData("residenceIdentifierInResponse", true, "familyHomes|mansions")] + [InlineData("dataInRoomResponse", true, "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("roomIdentifierInResponse", false, "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("dataInRoadResponse", true, "cyclePaths")] + [InlineData("roadIdentifierInResponse", false, "cyclePaths")] + public override async Task Expected_names_appear_in_type_discriminator_mapping(string schemaName, bool isWrapped, string? discriminatorValues) + { + await base.Expected_names_appear_in_type_discriminator_mapping(schemaName, isWrapped, discriminatorValues); + } + + [Theory] + [InlineData("attributesInCreateRequest", "familyHomes|mansions|residences|buildings")] + [InlineData("attributesInUpdateRequest", "familyHomes|mansions|residences|buildings")] + [InlineData("relationshipsInCreateRequest", "familyHomes|mansions|residences|buildings")] + [InlineData("relationshipsInUpdateRequest", "familyHomes|mansions|residences|buildings")] + [InlineData("!attributesInBuildingResponse", "familyHomes|mansions|residences")] + [InlineData("!relationshipsInBuildingResponse", "familyHomes|mansions|residences")] + [InlineData("!attributesInRoomResponse", "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("!relationshipsInRoomResponse", "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("!attributesInRoadResponse", "cyclePaths")] + [InlineData("!relationshipsInRoadResponse", "cyclePaths")] + [InlineData("atomicOperation", null)] + public override async Task Expected_names_appear_in_openapi_discriminator_mapping(string schemaName, string? discriminatorValues) + { + await base.Expected_names_appear_in_openapi_discriminator_mapping(schemaName, discriminatorValues); + } + + [Theory] + [InlineData("buildingResourceType", "familyHomes|mansions|residences")] + [InlineData("residenceResourceType", null)] + [InlineData("familyHomeResourceType", null)] + [InlineData("mansionResourceType", null)] + [InlineData("roomResourceType", "bathrooms|bedrooms|kitchens|livingRooms|toilets")] + [InlineData("bathroomResourceType", null)] + [InlineData("bedroomResourceType", null)] + [InlineData("kitchenResourceType", null)] + [InlineData("livingRoomResourceType", null)] + [InlineData("toiletResourceType", null)] + [InlineData("roadResourceType", "roads|cyclePaths")] + [InlineData("cyclePathResourceType", null)] + [InlineData("districtResourceType", null)] + [InlineData("staffMemberResourceType", "staffMembers")] + [InlineData("resourceType", + "bathrooms|bedrooms|kitchens|livingRooms|toilets|rooms|familyHomes|mansions|residences|buildings|roads|cyclePaths|districts|staffMembers")] + public override async Task Expected_names_appear_in_resource_type_enum(string schemaName, string? enumValues) + { + await base.Expected_names_appear_in_resource_type_enum(schemaName, enumValues); + } + + [Theory] + [InlineData("resourceInCreateRequest", true, null, "type|meta")] + [InlineData("attributesInCreateRequest", true, null, "openapi:discriminator")] + [InlineData("relationshipsInCreateRequest", true, null, "openapi:discriminator")] + [InlineData("resourceInUpdateRequest", true, null, "type|meta")] + [InlineData("attributesInUpdateRequest", true, null, "openapi:discriminator")] + [InlineData("relationshipsInUpdateRequest", true, null, "openapi:discriminator")] + [InlineData("identifierInRequest", true, null, "type|meta")] + [InlineData("resourceInResponse", true, null, "type|meta")] + [InlineData("atomicOperation", true, null, null)] + // Building hierarchy: Resource Data + [InlineData("dataInCreateBuildingRequest", true, "resourceInCreateRequest", "attributes|relationships")] + [InlineData("dataInCreateResidenceRequest", false, "dataInCreateBuildingRequest", null)] + [InlineData("dataInCreateFamilyHomeRequest", false, "dataInCreateResidenceRequest", null)] + [InlineData("dataInCreateMansionRequest", false, "dataInCreateResidenceRequest", null)] + [InlineData("dataInUpdateBuildingRequest", true, "resourceInUpdateRequest", "id|attributes|relationships")] + [InlineData("dataInUpdateResidenceRequest", false, "dataInUpdateBuildingRequest", null)] + [InlineData("dataInUpdateFamilyHomeRequest", false, "dataInUpdateResidenceRequest", null)] + [InlineData("dataInUpdateMansionRequest", false, "dataInUpdateResidenceRequest", null)] + [InlineData("dataInBuildingResponse", true, "resourceInResponse", "id|attributes|relationships|links")] + [InlineData("dataInResidenceResponse", false, "dataInBuildingResponse", null)] + [InlineData("dataInFamilyHomeResponse", false, "dataInResidenceResponse", null)] + [InlineData("dataInMansionResponse", false, "dataInResidenceResponse", null)] + // Building hierarchy: Attributes + [InlineData("attributesInCreateBuildingRequest", true, "attributesInCreateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInCreateResidenceRequest", false, "attributesInCreateBuildingRequest", "numberOfResidents")] + [InlineData("attributesInCreateFamilyHomeRequest", false, "attributesInCreateResidenceRequest", "floorCount")] + [InlineData("attributesInCreateMansionRequest", false, "attributesInCreateResidenceRequest", "ownerName")] + [InlineData("attributesInUpdateBuildingRequest", true, "attributesInUpdateRequest", "surfaceInSquareMeters")] + [InlineData("attributesInUpdateResidenceRequest", false, "attributesInUpdateBuildingRequest", "numberOfResidents")] + [InlineData("attributesInUpdateFamilyHomeRequest", false, "attributesInUpdateResidenceRequest", "floorCount")] + [InlineData("attributesInUpdateMansionRequest", false, "attributesInUpdateResidenceRequest", "ownerName")] + [InlineData("attributesInBuildingResponse", true, "attributesInResponse", "surfaceInSquareMeters")] + [InlineData("attributesInResidenceResponse", false, "attributesInBuildingResponse", "numberOfResidents")] + [InlineData("attributesInFamilyHomeResponse", false, "attributesInResidenceResponse", "floorCount")] + [InlineData("attributesInMansionResponse", false, "attributesInResidenceResponse", "ownerName")] + // Building hierarchy: Relationships + [InlineData("relationshipsInCreateBuildingRequest", true, "relationshipsInCreateRequest", null)] + [InlineData("relationshipsInCreateResidenceRequest", false, "relationshipsInCreateBuildingRequest", "rooms")] + [InlineData("relationshipsInCreateFamilyHomeRequest", false, "relationshipsInCreateResidenceRequest", null)] + [InlineData("relationshipsInCreateMansionRequest", false, "relationshipsInCreateResidenceRequest", "staff")] + [InlineData("relationshipsInUpdateBuildingRequest", true, "relationshipsInUpdateRequest", null)] + [InlineData("relationshipsInUpdateResidenceRequest", false, "relationshipsInUpdateBuildingRequest", "rooms")] + [InlineData("relationshipsInUpdateFamilyHomeRequest", false, "relationshipsInUpdateResidenceRequest", null)] + [InlineData("relationshipsInUpdateMansionRequest", false, "relationshipsInUpdateResidenceRequest", "staff")] + [InlineData("relationshipsInBuildingResponse", true, "relationshipsInResponse", null)] + [InlineData("relationshipsInResidenceResponse", false, "relationshipsInBuildingResponse", "rooms")] + [InlineData("relationshipsInFamilyHomeResponse", false, "relationshipsInResidenceResponse", null)] + [InlineData("relationshipsInMansionResponse", false, "relationshipsInResidenceResponse", "staff")] + // Building hierarchy: Resource Identifiers + [InlineData("buildingIdentifierInRequest", false, null, null)] + [InlineData("residenceIdentifierInRequest", false, null, null)] + [InlineData("familyHomeIdentifierInRequest", false, null, null)] + [InlineData("mansionIdentifierInRequest", false, null, null)] + [InlineData("buildingIdentifierInResponse", true, null, "type|id|meta")] + [InlineData("residenceIdentifierInResponse", false, "buildingIdentifierInResponse", null)] + [InlineData("familyHomeIdentifierInResponse", false, "residenceIdentifierInResponse", null)] + [InlineData("mansionIdentifierInResponse", false, "residenceIdentifierInResponse", null)] + // Building hierarchy: Atomic Operations + [InlineData("createBuildingOperation", false, null, null)] + [InlineData("createResidenceOperation", false, null, null)] + [InlineData("createFamilyHomeOperation", false, null, null)] + [InlineData("createMansionOperation", false, null, null)] + [InlineData("updateBuildingOperation", false, null, null)] + [InlineData("updateResidenceOperation", false, null, null)] + [InlineData("updateFamilyHomeOperation", false, null, null)] + [InlineData("updateMansionOperation", false, null, null)] + [InlineData("deleteBuildingOperation", false, null, null)] + [InlineData("deleteResidenceOperation", false, null, null)] + [InlineData("deleteFamilyHomeOperation", false, null, null)] + [InlineData("deleteMansionOperation", false, null, null)] + [InlineData("updateResidenceRoomsRelationshipOperation", false, null, null)] + [InlineData("updateFamilyHomeRoomsRelationshipOperation", false, null, null)] + [InlineData("updateMansionRoomsRelationshipOperation", false, null, null)] + [InlineData("updateMansionStaffRelationshipOperation", false, null, null)] + [InlineData("addToResidenceRoomsRelationshipOperation", false, null, null)] + [InlineData("addToFamilyHomeRoomsRelationshipOperation", false, null, null)] + [InlineData("addToMansionRoomsRelationshipOperation", false, null, null)] + [InlineData("addToMansionStaffRelationshipOperation", false, null, null)] + [InlineData("removeFromResidenceRoomsRelationshipOperation", false, null, null)] + [InlineData("removeFromFamilyHomeRoomsRelationshipOperation", false, null, null)] + [InlineData("removeFromMansionRoomsRelationshipOperation", false, null, null)] + [InlineData("removeFromMansionStaffRelationshipOperation", false, null, null)] + // Room hierarchy: Resource Data + [InlineData("dataInCreateRoomRequest", true, null, null)] + [InlineData("dataInCreateBathroomRequest", false, null, null)] + [InlineData("dataInCreateBedroomRequest", false, null, null)] + [InlineData("dataInCreateKitchenRequest", false, null, null)] + [InlineData("dataInCreateLivingRoomRequest", false, null, null)] + [InlineData("dataInCreateToiletRequest", false, null, null)] + [InlineData("dataInUpdateRoomRequest", true, null, null)] + [InlineData("dataInUpdateBathroomRequest", false, null, null)] + [InlineData("dataInUpdateBedroomRequest", false, null, null)] + [InlineData("dataInUpdateKitchenRequest", false, null, null)] + [InlineData("dataInUpdateLivingRoomRequest", false, null, null)] + [InlineData("dataInUpdateToiletRequest", false, null, null)] + [InlineData("dataInRoomResponse", true, "resourceInResponse", "id|attributes|relationships|links")] + [InlineData("dataInBathroomResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInBedroomResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInKitchenResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInLivingRoomResponse", false, "dataInRoomResponse", null)] + [InlineData("dataInToiletResponse", false, "dataInRoomResponse", null)] + // Room hierarchy: Attributes + [InlineData("attributesInCreateRoomRequest", true, null, null)] + [InlineData("attributesInCreateBathroomRequest", false, null, null)] + [InlineData("attributesInCreateBedroomRequest", false, null, null)] + [InlineData("attributesInCreateKitchenRequest", false, null, null)] + [InlineData("attributesInCreateLivingRoomRequest", false, null, null)] + [InlineData("attributesInCreateToiletRequest", false, null, null)] + [InlineData("attributesInUpdateRoomRequest", true, null, null)] + [InlineData("attributesInUpdateBathroomRequest", false, null, null)] + [InlineData("attributesInUpdateBedroomRequest", false, null, null)] + [InlineData("attributesInUpdateKitchenRequest", false, null, null)] + [InlineData("attributesInUpdateLivingRoomRequest", false, null, null)] + [InlineData("attributesInUpdateToiletRequest", false, null, null)] + [InlineData("attributesInRoomResponse", true, "attributesInResponse", "surfaceInSquareMeters")] + [InlineData("attributesInBathroomResponse", false, "attributesInRoomResponse", "hasBath")] + [InlineData("attributesInBedroomResponse", false, "attributesInRoomResponse", "bedCount")] + [InlineData("attributesInKitchenResponse", false, "attributesInRoomResponse", "hasPantry")] + [InlineData("attributesInLivingRoomResponse", false, "attributesInRoomResponse", "hasDiningTable")] + [InlineData("attributesInToiletResponse", false, "attributesInRoomResponse", "hasSink")] + // Room hierarchy: Relationships + [InlineData("relationshipsInCreateRoomRequest", true, null, null)] + [InlineData("relationshipsInCreateBathroomRequest", false, null, null)] + [InlineData("relationshipsInCreateBedroomRequest", false, null, null)] + [InlineData("relationshipsInCreateKitchenRequest", false, null, null)] + [InlineData("relationshipsInCreateLivingRoomRequest", false, null, null)] + [InlineData("relationshipsInCreateToiletRequest", false, null, null)] + [InlineData("relationshipsInUpdateRoomRequest", true, null, null)] + [InlineData("relationshipsInUpdateBathroomRequest", false, null, null)] + [InlineData("relationshipsInUpdateBedroomRequest", false, null, null)] + [InlineData("relationshipsInUpdateKitchenRequest", false, null, null)] + [InlineData("relationshipsInUpdateLivingRoomRequest", false, null, null)] + [InlineData("relationshipsInUpdateToiletRequest", false, null, null)] + [InlineData("relationshipsInRoomResponse", true, "relationshipsInResponse", "residence")] + [InlineData("relationshipsInBathroomResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInBedroomResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInKitchenResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInLivingRoomResponse", false, "relationshipsInRoomResponse", null)] + [InlineData("relationshipsInToiletResponse", false, "relationshipsInRoomResponse", null)] + // Room hierarchy: Resource Identifiers + [InlineData("roomIdentifierInRequest", false, "identifierInRequest", "id")] + [InlineData("bathroomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("bedroomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("kitchenIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("livingRoomIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("toiletIdentifierInRequest", false, "roomIdentifierInRequest", null)] + [InlineData("roomIdentifierInResponse", true, null, "type|id|meta")] + [InlineData("bathroomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("bedroomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("kitchenIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("livingRoomIdentifierInResponse", false, "roomIdentifierInResponse", null)] + [InlineData("toiletIdentifierInResponse", false, "roomIdentifierInResponse", null)] + // Room hierarchy: Atomic Operations + [InlineData("createRoomOperation", false, null, null)] + [InlineData("createBathroomOperation", false, null, null)] + [InlineData("createBedroomOperation", false, null, null)] + [InlineData("createKitchenOperation", false, null, null)] + [InlineData("createLivingRoomOperation", false, null, null)] + [InlineData("createToiletOperation", false, null, null)] + [InlineData("updateRoomOperation", false, null, null)] + [InlineData("updateBathroomOperation", false, null, null)] + [InlineData("updateBedroomOperation", false, null, null)] + [InlineData("updateKitchenOperation", false, null, null)] + [InlineData("updateLivingRoomOperation", false, null, null)] + [InlineData("updateToiletOperation", false, null, null)] + [InlineData("deleteRoomOperation", false, null, null)] + [InlineData("deleteBathroomOperation", false, null, null)] + [InlineData("deleteBedroomOperation", false, null, null)] + [InlineData("deleteKitchenOperation", false, null, null)] + [InlineData("deleteLivingRoomOperation", false, null, null)] + [InlineData("deleteToiletOperation", false, null, null)] + [InlineData("updateRoomResidenceRelationshipOperation", false, null, null)] + [InlineData("updateBathroomResidenceRelationshipOperation", false, null, null)] + [InlineData("updateBedroomResidenceRelationshipOperation", false, null, null)] + [InlineData("updateKitchenResidenceRelationshipOperation", false, null, null)] + [InlineData("updateLivingRoomResidenceRelationshipOperation", false, null, null)] + [InlineData("updateToiletResidenceRelationshipOperation", false, null, null)] + // Road hierarchy: Resource Data + [InlineData("dataInCreateRoadRequest", false, null, null)] + [InlineData("dataInCreateCyclePathRequest", false, null, null)] + [InlineData("dataInUpdateRoadRequest", false, null, null)] + [InlineData("dataInUpdateCyclePathRequest", false, null, null)] + [InlineData("dataInRoadResponse", false, "resourceInResponse", "id|attributes|relationships|links")] + [InlineData("dataInCyclePathResponse", false, "dataInRoadResponse", null)] + // Road hierarchy: Attributes + [InlineData("attributesInCreateRoadRequest", false, null, null)] + [InlineData("attributesInCreateCyclePathRequest", false, null, null)] + [InlineData("attributesInUpdateRoadRequest", false, null, null)] + [InlineData("attributesInUpdateCyclePathRequest", false, null, null)] + [InlineData("attributesInRoadResponse", false, "attributesInResponse", "lengthInMeters")] + [InlineData("attributesInCyclePathResponse", false, "attributesInRoadResponse", "hasLaneForPedestrians")] + // Road hierarchy: Relationships + [InlineData("relationshipsInCreateRoadRequest", false, null, null)] + [InlineData("relationshipsInCreateCyclePathRequest", false, null, null)] + [InlineData("relationshipsInUpdateRoadRequest", false, null, null)] + [InlineData("relationshipsInUpdateCyclePathRequest", false, null, null)] + [InlineData("relationshipsInRoadResponse", false, "relationshipsInResponse", null)] + [InlineData("relationshipsInCyclePathResponse", false, "relationshipsInRoadResponse", null)] + // Road hierarchy: Resource Identifiers + [InlineData("roadIdentifierInRequest", false, null, null)] + [InlineData("cyclePathIdentifierInRequest", false, null, null)] + [InlineData("roadIdentifierInResponse", false, null, "type|id|meta")] + [InlineData("cyclePathIdentifierInResponse", false, "roadIdentifierInResponse", null)] + // Road hierarchy: Atomic Operations + [InlineData("createRoadOperation", false, null, null)] + [InlineData("createCyclePathOperation", false, null, null)] + [InlineData("updateRoadOperation", false, null, null)] + [InlineData("updateCyclePathOperation", false, null, null)] + [InlineData("deleteRoadOperation", false, null, null)] + [InlineData("deleteCyclePathOperation", false, null, null)] + public override async Task Component_schemas_have_expected_base_type(string schemaName, bool isAbstract, string? baseType, string? properties) + { + await base.Component_schemas_have_expected_base_type(schemaName, isAbstract, baseType, properties); + } +} diff --git a/test/OpenApiTests/ResourceInheritance/SubsetOfVarious/SubsetOfVariousOperationFilter.cs b/test/OpenApiTests/ResourceInheritance/SubsetOfVarious/SubsetOfVariousOperationFilter.cs new file mode 100644 index 0000000000..8543e1d86f --- /dev/null +++ b/test/OpenApiTests/ResourceInheritance/SubsetOfVarious/SubsetOfVariousOperationFilter.cs @@ -0,0 +1,36 @@ +using JsonApiDotNetCore.AtomicOperations; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using OpenApiTests.ResourceInheritance.Models; + +namespace OpenApiTests.ResourceInheritance.SubsetOfVarious; + +public sealed class SubsetOfVariousOperationFilter : DefaultOperationFilter +{ + protected override JsonApiEndpoints? GetJsonApiEndpoints(ResourceType resourceType) + { + Type resourceClrType = resourceType.ClrType; + + if (resourceClrType == typeof(District)) + { + return JsonApiEndpoints.GetCollection; + } + + if (resourceClrType == typeof(Building)) + { + return JsonApiEndpoints.Post | JsonApiEndpoints.Patch; + } + + if (resourceClrType == typeof(FamilyHome)) + { + return JsonApiEndpoints.GetRelationship; + } + + if (resourceClrType == typeof(CyclePath)) + { + return JsonApiEndpoints.GetSingle; + } + + return JsonApiEndpoints.None; + } +} diff --git a/test/OpenApiTests/RestrictedControllers/Channel.cs b/test/OpenApiTests/RestrictedControllers/Channel.cs new file mode 100644 index 0000000000..a91555582d --- /dev/null +++ b/test/OpenApiTests/RestrictedControllers/Channel.cs @@ -0,0 +1,27 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.RestrictedControllers; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public abstract class Channel : Identifiable +{ + [Attr] + public string? Name { get; set; } + + [Attr] + public bool? IsCommercial { get; set; } + + [Attr] + public bool? IsAdultOnly { get; set; } + + [HasOne] + public DataStream VideoStream { get; set; } = null!; + + [HasOne] + public DataStream? UltraHighDefinitionVideoStream { get; set; } + + [HasMany] + public ISet AudioStreams { get; set; } = new HashSet(); +} diff --git a/test/OpenApiTests/RestrictedControllers/DataStream.cs b/test/OpenApiTests/RestrictedControllers/DataStream.cs new file mode 100644 index 0000000000..a92ef3e76b --- /dev/null +++ b/test/OpenApiTests/RestrictedControllers/DataStream.cs @@ -0,0 +1,18 @@ +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.RestrictedControllers; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.RestrictedControllers", GenerateControllerEndpoints = JsonApiEndpoints.None)] +#pragma warning disable CA1711 // Identifiers should not have incorrect suffix +public sealed class DataStream : Identifiable +#pragma warning restore CA1711 // Identifiers should not have incorrect suffix +{ + [Attr] + [Required] + public ulong? BytesTransmitted { get; set; } +} diff --git a/test/OpenApiTests/RestrictedControllers/DataStreamController.cs b/test/OpenApiTests/RestrictedControllers/DataStreamController.cs new file mode 100644 index 0000000000..1496d51dfb --- /dev/null +++ b/test/OpenApiTests/RestrictedControllers/DataStreamController.cs @@ -0,0 +1,26 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Services; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; + +namespace OpenApiTests.RestrictedControllers; + +public sealed class DataStreamController( + IJsonApiOptions options, IResourceGraph resourceGraph, ILoggerFactory loggerFactory, IResourceService resourceService) + : BaseJsonApiController(options, resourceGraph, loggerFactory, resourceService) +{ + [HttpGet] + [HttpHead] + public override Task GetAsync(CancellationToken cancellationToken) + { + return base.GetAsync(cancellationToken); + } + + [HttpGet("{id}")] + [HttpHead("{id}")] + public override Task GetAsync(long id, CancellationToken cancellationToken) + { + return base.GetAsync(id, cancellationToken); + } +} diff --git a/test/OpenApiTests/RestrictedControllers/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/RestrictedControllers/GeneratedSwagger/swagger.g.json new file mode 100644 index 0000000000..51cc607974 --- /dev/null +++ b/test/OpenApiTests/RestrictedControllers/GeneratedSwagger/swagger.g.json @@ -0,0 +1,5914 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "OpenApiTests", + "version": "1.0" + }, + "servers": [ + { + "url": "http://localhost" + } + ], + "paths": { + "/dataStreams": { + "get": { + "tags": [ + "dataStreams" + ], + "summary": "Retrieves a collection of dataStreams.", + "operationId": "getDataStreamCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found dataStreams, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/dataStreamCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "dataStreams" + ], + "summary": "Retrieves a collection of dataStreams without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headDataStreamCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + } + }, + "/dataStreams/{id}": { + "get": { + "tags": [ + "dataStreams" + ], + "summary": "Retrieves an individual dataStream by its identifier.", + "operationId": "getDataStream", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the dataStream to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found dataStream.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryDataStreamResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The dataStream does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "dataStreams" + ], + "summary": "Retrieves an individual dataStream by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headDataStream", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the dataStream to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The dataStream does not exist." + } + } + } + }, + "/readOnlyChannels": { + "get": { + "tags": [ + "readOnlyChannels" + ], + "summary": "Retrieves a collection of readOnlyChannels.", + "operationId": "getReadOnlyChannelCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found readOnlyChannels, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/readOnlyChannelCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "readOnlyChannels" + ], + "summary": "Retrieves a collection of readOnlyChannels without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headReadOnlyChannelCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + } + }, + "/readOnlyChannels/{id}": { + "get": { + "tags": [ + "readOnlyChannels" + ], + "summary": "Retrieves an individual readOnlyChannel by its identifier.", + "operationId": "getReadOnlyChannel", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the readOnlyChannel to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found readOnlyChannel.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryReadOnlyChannelResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The readOnlyChannel does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "readOnlyChannels" + ], + "summary": "Retrieves an individual readOnlyChannel by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headReadOnlyChannel", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the readOnlyChannel to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The readOnlyChannel does not exist." + } + } + } + }, + "/readOnlyChannels/{id}/audioStreams": { + "get": { + "tags": [ + "readOnlyChannels" + ], + "summary": "Retrieves the related dataStreams of an individual readOnlyChannel's audioStreams relationship.", + "operationId": "getReadOnlyChannelAudioStreams", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the readOnlyChannel whose related dataStreams to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found dataStreams, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/dataStreamCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The readOnlyChannel does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "readOnlyChannels" + ], + "summary": "Retrieves the related dataStreams of an individual readOnlyChannel's audioStreams relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headReadOnlyChannelAudioStreams", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the readOnlyChannel whose related dataStreams to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The readOnlyChannel does not exist." + } + } + } + }, + "/readOnlyChannels/{id}/relationships/audioStreams": { + "get": { + "tags": [ + "readOnlyChannels" + ], + "summary": "Retrieves the related dataStream identities of an individual readOnlyChannel's audioStreams relationship.", + "operationId": "getReadOnlyChannelAudioStreamsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the readOnlyChannel whose related dataStream identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found dataStream identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/dataStreamIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The readOnlyChannel does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "readOnlyChannels" + ], + "summary": "Retrieves the related dataStream identities of an individual readOnlyChannel's audioStreams relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headReadOnlyChannelAudioStreamsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the readOnlyChannel whose related dataStream identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The readOnlyChannel does not exist." + } + } + } + }, + "/readOnlyChannels/{id}/ultraHighDefinitionVideoStream": { + "get": { + "tags": [ + "readOnlyChannels" + ], + "summary": "Retrieves the related dataStream of an individual readOnlyChannel's ultraHighDefinitionVideoStream relationship.", + "operationId": "getReadOnlyChannelUltraHighDefinitionVideoStream", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the readOnlyChannel whose related dataStream to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found dataStream, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullableSecondaryDataStreamResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The readOnlyChannel does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "readOnlyChannels" + ], + "summary": "Retrieves the related dataStream of an individual readOnlyChannel's ultraHighDefinitionVideoStream relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headReadOnlyChannelUltraHighDefinitionVideoStream", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the readOnlyChannel whose related dataStream to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The readOnlyChannel does not exist." + } + } + } + }, + "/readOnlyChannels/{id}/relationships/ultraHighDefinitionVideoStream": { + "get": { + "tags": [ + "readOnlyChannels" + ], + "summary": "Retrieves the related dataStream identity of an individual readOnlyChannel's ultraHighDefinitionVideoStream relationship.", + "operationId": "getReadOnlyChannelUltraHighDefinitionVideoStreamRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the readOnlyChannel whose related dataStream identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found dataStream identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullableDataStreamIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The readOnlyChannel does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "readOnlyChannels" + ], + "summary": "Retrieves the related dataStream identity of an individual readOnlyChannel's ultraHighDefinitionVideoStream relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headReadOnlyChannelUltraHighDefinitionVideoStreamRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the readOnlyChannel whose related dataStream identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The readOnlyChannel does not exist." + } + } + } + }, + "/readOnlyChannels/{id}/videoStream": { + "get": { + "tags": [ + "readOnlyChannels" + ], + "summary": "Retrieves the related dataStream of an individual readOnlyChannel's videoStream relationship.", + "operationId": "getReadOnlyChannelVideoStream", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the readOnlyChannel whose related dataStream to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found dataStream, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/secondaryDataStreamResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The readOnlyChannel does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "readOnlyChannels" + ], + "summary": "Retrieves the related dataStream of an individual readOnlyChannel's videoStream relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headReadOnlyChannelVideoStream", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the readOnlyChannel whose related dataStream to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The readOnlyChannel does not exist." + } + } + } + }, + "/readOnlyChannels/{id}/relationships/videoStream": { + "get": { + "tags": [ + "readOnlyChannels" + ], + "summary": "Retrieves the related dataStream identity of an individual readOnlyChannel's videoStream relationship.", + "operationId": "getReadOnlyChannelVideoStreamRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the readOnlyChannel whose related dataStream identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found dataStream identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/dataStreamIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The readOnlyChannel does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "readOnlyChannels" + ], + "summary": "Retrieves the related dataStream identity of an individual readOnlyChannel's videoStream relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headReadOnlyChannelVideoStreamRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the readOnlyChannel whose related dataStream identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The readOnlyChannel does not exist." + } + } + } + }, + "/readOnlyResourceChannels": { + "get": { + "tags": [ + "readOnlyResourceChannels" + ], + "summary": "Retrieves a collection of readOnlyResourceChannels.", + "operationId": "getReadOnlyResourceChannelCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found readOnlyResourceChannels, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/readOnlyResourceChannelCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "readOnlyResourceChannels" + ], + "summary": "Retrieves a collection of readOnlyResourceChannels without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headReadOnlyResourceChannelCollection", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + } + } + } + }, + "/readOnlyResourceChannels/{id}": { + "get": { + "tags": [ + "readOnlyResourceChannels" + ], + "summary": "Retrieves an individual readOnlyResourceChannel by its identifier.", + "operationId": "getReadOnlyResourceChannel", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the readOnlyResourceChannel to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found readOnlyResourceChannel.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryReadOnlyResourceChannelResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The readOnlyResourceChannel does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "readOnlyResourceChannels" + ], + "summary": "Retrieves an individual readOnlyResourceChannel by its identifier without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headReadOnlyResourceChannel", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the readOnlyResourceChannel to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The readOnlyResourceChannel does not exist." + } + } + } + }, + "/readOnlyResourceChannels/{id}/audioStreams": { + "get": { + "tags": [ + "readOnlyResourceChannels" + ], + "summary": "Retrieves the related dataStreams of an individual readOnlyResourceChannel's audioStreams relationship.", + "operationId": "getReadOnlyResourceChannelAudioStreams", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the readOnlyResourceChannel whose related dataStreams to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found dataStreams, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/dataStreamCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The readOnlyResourceChannel does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "readOnlyResourceChannels" + ], + "summary": "Retrieves the related dataStreams of an individual readOnlyResourceChannel's audioStreams relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headReadOnlyResourceChannelAudioStreams", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the readOnlyResourceChannel whose related dataStreams to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The readOnlyResourceChannel does not exist." + } + } + } + }, + "/readOnlyResourceChannels/{id}/ultraHighDefinitionVideoStream": { + "get": { + "tags": [ + "readOnlyResourceChannels" + ], + "summary": "Retrieves the related dataStream of an individual readOnlyResourceChannel's ultraHighDefinitionVideoStream relationship.", + "operationId": "getReadOnlyResourceChannelUltraHighDefinitionVideoStream", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the readOnlyResourceChannel whose related dataStream to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found dataStream, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullableSecondaryDataStreamResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The readOnlyResourceChannel does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "readOnlyResourceChannels" + ], + "summary": "Retrieves the related dataStream of an individual readOnlyResourceChannel's ultraHighDefinitionVideoStream relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headReadOnlyResourceChannelUltraHighDefinitionVideoStream", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the readOnlyResourceChannel whose related dataStream to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The readOnlyResourceChannel does not exist." + } + } + } + }, + "/readOnlyResourceChannels/{id}/videoStream": { + "get": { + "tags": [ + "readOnlyResourceChannels" + ], + "summary": "Retrieves the related dataStream of an individual readOnlyResourceChannel's videoStream relationship.", + "operationId": "getReadOnlyResourceChannelVideoStream", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the readOnlyResourceChannel whose related dataStream to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found dataStream, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/secondaryDataStreamResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The readOnlyResourceChannel does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "readOnlyResourceChannels" + ], + "summary": "Retrieves the related dataStream of an individual readOnlyResourceChannel's videoStream relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headReadOnlyResourceChannelVideoStream", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the readOnlyResourceChannel whose related dataStream to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The readOnlyResourceChannel does not exist." + } + } + } + }, + "/relationshipChannels/{id}/relationships/audioStreams": { + "get": { + "tags": [ + "relationshipChannels" + ], + "summary": "Retrieves the related dataStream identities of an individual relationshipChannel's audioStreams relationship.", + "operationId": "getRelationshipChannelAudioStreamsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the relationshipChannel whose related dataStream identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found dataStream identities, or an empty array if none were found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/dataStreamIdentifierCollectionResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The relationshipChannel does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "relationshipChannels" + ], + "summary": "Retrieves the related dataStream identities of an individual relationshipChannel's audioStreams relationship without returning them.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headRelationshipChannelAudioStreamsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the relationshipChannel whose related dataStream identities to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The relationshipChannel does not exist." + } + } + }, + "post": { + "tags": [ + "relationshipChannels" + ], + "summary": "Adds existing dataStreams to the audioStreams relationship of an individual relationshipChannel.", + "operationId": "postRelationshipChannelAudioStreamsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the relationshipChannel to add dataStreams to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the dataStreams to add to the audioStreams relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyDataStreamInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The dataStreams were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The relationshipChannel or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "relationshipChannels" + ], + "summary": "Assigns existing dataStreams to the audioStreams relationship of an individual relationshipChannel.", + "operationId": "patchRelationshipChannelAudioStreamsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the relationshipChannel whose audioStreams relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the dataStreams to assign to the audioStreams relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyDataStreamInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The audioStreams relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The relationshipChannel or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "relationshipChannels" + ], + "summary": "Removes existing dataStreams from the audioStreams relationship of an individual relationshipChannel.", + "operationId": "deleteRelationshipChannelAudioStreamsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the relationshipChannel to remove dataStreams from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the dataStreams to remove from the audioStreams relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyDataStreamInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The dataStreams were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The relationshipChannel or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/relationshipChannels/{id}/relationships/ultraHighDefinitionVideoStream": { + "get": { + "tags": [ + "relationshipChannels" + ], + "summary": "Retrieves the related dataStream identity of an individual relationshipChannel's ultraHighDefinitionVideoStream relationship.", + "operationId": "getRelationshipChannelUltraHighDefinitionVideoStreamRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the relationshipChannel whose related dataStream identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found dataStream identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/nullableDataStreamIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The relationshipChannel does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "relationshipChannels" + ], + "summary": "Retrieves the related dataStream identity of an individual relationshipChannel's ultraHighDefinitionVideoStream relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headRelationshipChannelUltraHighDefinitionVideoStreamRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the relationshipChannel whose related dataStream identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The relationshipChannel does not exist." + } + } + }, + "patch": { + "tags": [ + "relationshipChannels" + ], + "summary": "Clears or assigns an existing dataStream to the ultraHighDefinitionVideoStream relationship of an individual relationshipChannel.", + "operationId": "patchRelationshipChannelUltraHighDefinitionVideoStreamRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the relationshipChannel whose ultraHighDefinitionVideoStream relationship to assign or clear.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identity of the dataStream to assign to the ultraHighDefinitionVideoStream relationship, or `null` to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneDataStreamInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The ultraHighDefinitionVideoStream relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The relationshipChannel or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/relationshipChannels/{id}/relationships/videoStream": { + "get": { + "tags": [ + "relationshipChannels" + ], + "summary": "Retrieves the related dataStream identity of an individual relationshipChannel's videoStream relationship.", + "operationId": "getRelationshipChannelVideoStreamRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the relationshipChannel whose related dataStream identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully returns the found dataStream identity, or `null` if it was not found.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/dataStreamIdentifierResponseDocument" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The relationshipChannel does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "head": { + "tags": [ + "relationshipChannels" + ], + "summary": "Retrieves the related dataStream identity of an individual relationshipChannel's videoStream relationship without returning it.", + "description": "Compare the returned ETag HTTP header with an earlier one to determine if the response has changed since it was fetched.", + "operationId": "headRelationshipChannelVideoStreamRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the relationshipChannel whose related dataStream identity to retrieve.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + }, + { + "name": "If-None-Match", + "in": "header", + "description": "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The operation completed successfully.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + }, + "Content-Length": { + "description": "Size of the HTTP response body, in bytes.", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "304": { + "description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If-None-Match header.", + "headers": { + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "The query string is invalid." + }, + "404": { + "description": "The relationshipChannel does not exist." + } + } + }, + "patch": { + "tags": [ + "relationshipChannels" + ], + "summary": "Assigns an existing dataStream to the videoStream relationship of an individual relationshipChannel.", + "operationId": "patchRelationshipChannelVideoStreamRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the relationshipChannel whose videoStream relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identity of the dataStream to assign to the videoStream relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneDataStreamInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The videoStream relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The relationshipChannel or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/writeOnlyChannels": { + "post": { + "tags": [ + "writeOnlyChannels" + ], + "summary": "Creates a new writeOnlyChannel.", + "operationId": "postWriteOnlyChannel", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the writeOnlyChannel to create.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/createWriteOnlyChannelRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The writeOnlyChannel was successfully created, which resulted in additional changes. The newly created writeOnlyChannel is returned.", + "headers": { + "Location": { + "description": "The URL at which the newly created writeOnlyChannel can be retrieved.", + "required": true, + "schema": { + "type": "string", + "format": "uri" + } + } + }, + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryWriteOnlyChannelResponseDocument" + } + } + } + }, + "204": { + "description": "The writeOnlyChannel was successfully created, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "403": { + "description": "Client-generated IDs cannot be used at this endpoint.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "A related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/writeOnlyChannels/{id}": { + "patch": { + "tags": [ + "writeOnlyChannels" + ], + "summary": "Updates an existing writeOnlyChannel.", + "operationId": "patchWriteOnlyChannel", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the writeOnlyChannel to update.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + { + "name": "query", + "in": "query", + "description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string", + "nullable": true + }, + "example": "" + } + } + ], + "requestBody": { + "description": "The attributes and relationships of the writeOnlyChannel to update. Omitted fields are left unchanged.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/updateWriteOnlyChannelRequestDocument" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The writeOnlyChannel was successfully updated, which resulted in additional changes. The updated writeOnlyChannel is returned.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/primaryWriteOnlyChannelResponseDocument" + } + } + } + }, + "204": { + "description": "The writeOnlyChannel was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The query string is invalid or the request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The writeOnlyChannel or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "A resource type or identifier in the request body is incompatible.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "writeOnlyChannels" + ], + "summary": "Deletes an existing writeOnlyChannel by its identifier.", + "operationId": "deleteWriteOnlyChannel", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the writeOnlyChannel to delete.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "The writeOnlyChannel was successfully deleted." + }, + "404": { + "description": "The writeOnlyChannel does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/writeOnlyChannels/{id}/relationships/audioStreams": { + "post": { + "tags": [ + "writeOnlyChannels" + ], + "summary": "Adds existing dataStreams to the audioStreams relationship of an individual writeOnlyChannel.", + "operationId": "postWriteOnlyChannelAudioStreamsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the writeOnlyChannel to add dataStreams to.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the dataStreams to add to the audioStreams relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyDataStreamInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The dataStreams were successfully added, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The writeOnlyChannel or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "patch": { + "tags": [ + "writeOnlyChannels" + ], + "summary": "Assigns existing dataStreams to the audioStreams relationship of an individual writeOnlyChannel.", + "operationId": "patchWriteOnlyChannelAudioStreamsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the writeOnlyChannel whose audioStreams relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the dataStreams to assign to the audioStreams relationship, or an empty array to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyDataStreamInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The audioStreams relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The writeOnlyChannel or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + }, + "delete": { + "tags": [ + "writeOnlyChannels" + ], + "summary": "Removes existing dataStreams from the audioStreams relationship of an individual writeOnlyChannel.", + "operationId": "deleteWriteOnlyChannelAudioStreamsRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the writeOnlyChannel to remove dataStreams from.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identities of the dataStreams to remove from the audioStreams relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyDataStreamInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The dataStreams were successfully removed, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The writeOnlyChannel or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/writeOnlyChannels/{id}/relationships/ultraHighDefinitionVideoStream": { + "patch": { + "tags": [ + "writeOnlyChannels" + ], + "summary": "Clears or assigns an existing dataStream to the ultraHighDefinitionVideoStream relationship of an individual writeOnlyChannel.", + "operationId": "patchWriteOnlyChannelUltraHighDefinitionVideoStreamRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the writeOnlyChannel whose ultraHighDefinitionVideoStream relationship to assign or clear.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identity of the dataStream to assign to the ultraHighDefinitionVideoStream relationship, or `null` to clear the relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneDataStreamInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The ultraHighDefinitionVideoStream relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The writeOnlyChannel or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + }, + "/writeOnlyChannels/{id}/relationships/videoStream": { + "patch": { + "tags": [ + "writeOnlyChannels" + ], + "summary": "Assigns an existing dataStream to the videoStream relationship of an individual writeOnlyChannel.", + "operationId": "patchWriteOnlyChannelVideoStreamRelationship", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The identifier of the writeOnlyChannel whose videoStream relationship to assign.", + "required": true, + "schema": { + "minLength": 1, + "type": "string", + "format": "int64" + } + } + ], + "requestBody": { + "description": "The identity of the dataStream to assign to the videoStream relationship.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneDataStreamInRequest" + } + ] + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "The videoStream relationship was successfully updated, which did not result in additional changes." + }, + "400": { + "description": "The request body is missing or malformed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "404": { + "description": "The writeOnlyChannel or a related resource does not exist.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "409": { + "description": "The request body contains conflicting information or another resource with the same ID already exists.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + }, + "422": { + "description": "Validation of the request body failed.", + "content": { + "application/vnd.api+json; ext=openapi": { + "schema": { + "$ref": "#/components/schemas/errorResponseDocument" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "attributesInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "writeOnlyChannels": "#/components/schemas/attributesInCreateWriteOnlyChannelRequest" + } + }, + "x-abstract": true + }, + "attributesInCreateWriteOnlyChannelRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateRequest" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true + }, + "isCommercial": { + "type": "boolean", + "nullable": true + }, + "isAdultOnly": { + "type": "boolean", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInDataStreamResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "bytesTransmitted": { + "type": "integer", + "format": "int64" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInReadOnlyChannelResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true + }, + "isCommercial": { + "type": "boolean", + "nullable": true + }, + "isAdultOnly": { + "type": "boolean", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInReadOnlyResourceChannelResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true + }, + "isCommercial": { + "type": "boolean", + "nullable": true + }, + "isAdultOnly": { + "type": "boolean", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "dataStreams": "#/components/schemas/attributesInDataStreamResponse", + "readOnlyChannels": "#/components/schemas/attributesInReadOnlyChannelResponse", + "readOnlyResourceChannels": "#/components/schemas/attributesInReadOnlyResourceChannelResponse", + "writeOnlyChannels": "#/components/schemas/attributesInWriteOnlyChannelResponse" + } + }, + "x-abstract": true + }, + "attributesInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "writeOnlyChannels": "#/components/schemas/attributesInUpdateWriteOnlyChannelRequest" + } + }, + "x-abstract": true + }, + "attributesInUpdateWriteOnlyChannelRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateRequest" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true + }, + "isCommercial": { + "type": "boolean", + "nullable": true + }, + "isAdultOnly": { + "type": "boolean", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "attributesInWriteOnlyChannelResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInResponse" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true + }, + "isCommercial": { + "type": "boolean", + "nullable": true + }, + "isAdultOnly": { + "type": "boolean", + "nullable": true + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "createWriteOnlyChannelRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInCreateWriteOnlyChannelRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "dataInCreateWriteOnlyChannelRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInCreateRequest" + }, + { + "type": "object", + "properties": { + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInCreateWriteOnlyChannelRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateWriteOnlyChannelRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInDataStreamResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInDataStreamResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInReadOnlyChannelResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInReadOnlyChannelResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInReadOnlyChannelResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInReadOnlyResourceChannelResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInReadOnlyResourceChannelResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInReadOnlyResourceChannelResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInUpdateWriteOnlyChannelRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/resourceInUpdateRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInUpdateWriteOnlyChannelRequest" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateWriteOnlyChannelRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataInWriteOnlyChannelResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceInResponse" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "attributes": { + "allOf": [ + { + "$ref": "#/components/schemas/attributesInWriteOnlyChannelResponse" + } + ] + }, + "relationships": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInWriteOnlyChannelResponse" + } + ] + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceLinks" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataStreamCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInDataStreamResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "dataStreamIdentifierCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataStreamIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "dataStreamIdentifierInRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/identifierInRequest" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "dataStreamIdentifierInResponse": { + "required": [ + "id", + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/dataStreamResourceType" + } + ] + }, + "id": { + "minLength": 1, + "type": "string", + "format": "int64" + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "dataStreamIdentifierResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataStreamIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "dataStreamResourceType": { + "enum": [ + "dataStreams" + ], + "type": "string" + }, + "errorLinks": { + "type": "object", + "properties": { + "about": { + "type": "string", + "nullable": true + }, + "type": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorObject": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorLinks" + } + ], + "nullable": true + }, + "status": { + "type": "string" + }, + "code": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/errorSource" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorResponseDocument": { + "required": [ + "errors", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/errorTopLevelLinks" + } + ] + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/errorObject" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "errorSource": { + "type": "object", + "properties": { + "pointer": { + "type": "string", + "nullable": true + }, + "parameter": { + "type": "string", + "nullable": true + }, + "header": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "errorTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "identifierInRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "dataStreams": "#/components/schemas/dataStreamIdentifierInRequest" + } + }, + "x-abstract": true + }, + "meta": { + "type": "object", + "additionalProperties": { + "nullable": true + } + }, + "nullableDataStreamIdentifierResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceIdentifierTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataStreamIdentifierInResponse" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableSecondaryDataStreamResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInDataStreamResponse" + } + ], + "nullable": true + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableToOneDataStreamInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataStreamIdentifierInRequest" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "nullableToOneDataStreamInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataStreamIdentifierInResponse" + } + ], + "nullable": true + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryDataStreamResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInDataStreamResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryReadOnlyChannelResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInReadOnlyChannelResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryReadOnlyResourceChannelResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInReadOnlyResourceChannelResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "primaryWriteOnlyChannelResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInWriteOnlyChannelResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "readOnlyChannelCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInReadOnlyChannelResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "readOnlyResourceChannelCollectionResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceCollectionTopLevelLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataInReadOnlyResourceChannelResponse" + } + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "relationshipLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + } + }, + "additionalProperties": false + }, + "relationshipsInCreateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "writeOnlyChannels": "#/components/schemas/relationshipsInCreateWriteOnlyChannelRequest" + } + }, + "x-abstract": true + }, + "relationshipsInCreateWriteOnlyChannelRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInCreateRequest" + }, + { + "required": [ + "videoStream" + ], + "type": "object", + "properties": { + "videoStream": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneDataStreamInRequest" + } + ] + }, + "ultraHighDefinitionVideoStream": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneDataStreamInRequest" + } + ] + }, + "audioStreams": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyDataStreamInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInReadOnlyChannelResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "type": "object", + "properties": { + "videoStream": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneDataStreamInResponse" + } + ] + }, + "ultraHighDefinitionVideoStream": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneDataStreamInResponse" + } + ] + }, + "audioStreams": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyDataStreamInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInReadOnlyResourceChannelResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "type": "object", + "properties": { + "videoStream": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneDataStreamInResponse" + } + ] + }, + "ultraHighDefinitionVideoStream": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneDataStreamInResponse" + } + ] + }, + "audioStreams": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyDataStreamInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInResponse": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "readOnlyChannels": "#/components/schemas/relationshipsInReadOnlyChannelResponse", + "readOnlyResourceChannels": "#/components/schemas/relationshipsInReadOnlyResourceChannelResponse", + "writeOnlyChannels": "#/components/schemas/relationshipsInWriteOnlyChannelResponse" + } + }, + "x-abstract": true + }, + "relationshipsInUpdateRequest": { + "required": [ + "openapi:discriminator" + ], + "type": "object", + "properties": { + "openapi:discriminator": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "openapi:discriminator", + "mapping": { + "writeOnlyChannels": "#/components/schemas/relationshipsInUpdateWriteOnlyChannelRequest" + } + }, + "x-abstract": true + }, + "relationshipsInUpdateWriteOnlyChannelRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInUpdateRequest" + }, + { + "type": "object", + "properties": { + "videoStream": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneDataStreamInRequest" + } + ] + }, + "ultraHighDefinitionVideoStream": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneDataStreamInRequest" + } + ] + }, + "audioStreams": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyDataStreamInRequest" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "relationshipsInWriteOnlyChannelResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipsInResponse" + }, + { + "type": "object", + "properties": { + "videoStream": { + "allOf": [ + { + "$ref": "#/components/schemas/toOneDataStreamInResponse" + } + ] + }, + "ultraHighDefinitionVideoStream": { + "allOf": [ + { + "$ref": "#/components/schemas/nullableToOneDataStreamInResponse" + } + ] + }, + "audioStreams": { + "allOf": [ + { + "$ref": "#/components/schemas/toManyDataStreamInResponse" + } + ] + } + }, + "additionalProperties": false + } + ], + "additionalProperties": false + }, + "resourceCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceIdentifierCollectionTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + }, + "first": { + "type": "string" + }, + "last": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceIdentifierTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "related": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceInCreateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "writeOnlyChannels": "#/components/schemas/dataInCreateWriteOnlyChannelRequest" + } + }, + "x-abstract": true + }, + "resourceInResponse": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "dataStreams": "#/components/schemas/dataInDataStreamResponse", + "readOnlyChannels": "#/components/schemas/dataInReadOnlyChannelResponse", + "readOnlyResourceChannels": "#/components/schemas/dataInReadOnlyResourceChannelResponse", + "writeOnlyChannels": "#/components/schemas/dataInWriteOnlyChannelResponse" + } + }, + "x-abstract": true + }, + "resourceInUpdateRequest": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceType" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "type", + "mapping": { + "writeOnlyChannels": "#/components/schemas/dataInUpdateWriteOnlyChannelRequest" + } + }, + "x-abstract": true + }, + "resourceLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceTopLevelLinks": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "describedby": { + "type": "string" + } + }, + "additionalProperties": false + }, + "resourceType": { + "enum": [ + "dataStreams", + "readOnlyChannels", + "readOnlyResourceChannels", + "writeOnlyChannels" + ], + "type": "string" + }, + "secondaryDataStreamResponseDocument": { + "required": [ + "data", + "links" + ], + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/resourceTopLevelLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInDataStreamResponse" + } + ] + }, + "included": { + "type": "array", + "items": { + "$ref": "#/components/schemas/resourceInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyDataStreamInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataStreamIdentifierInRequest" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toManyDataStreamInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataStreamIdentifierInResponse" + } + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneDataStreamInRequest": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataStreamIdentifierInRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "toOneDataStreamInResponse": { + "type": "object", + "properties": { + "links": { + "allOf": [ + { + "$ref": "#/components/schemas/relationshipLinks" + } + ] + }, + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataStreamIdentifierInResponse" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + }, + "updateWriteOnlyChannelRequestDocument": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/components/schemas/dataInUpdateWriteOnlyChannelRequest" + } + ] + }, + "meta": { + "allOf": [ + { + "$ref": "#/components/schemas/meta" + } + ] + } + }, + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/test/OpenApiTests/RestrictedControllers/ReadOnlyChannel.cs b/test/OpenApiTests/RestrictedControllers/ReadOnlyChannel.cs new file mode 100644 index 0000000000..50f3094eaa --- /dev/null +++ b/test/OpenApiTests/RestrictedControllers/ReadOnlyChannel.cs @@ -0,0 +1,12 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.RestrictedControllers; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.RestrictedControllers", GenerateControllerEndpoints = ControllerEndpoints)] +public sealed class ReadOnlyChannel : Channel +{ + internal const JsonApiEndpoints ControllerEndpoints = JsonApiEndpoints.Query; +} diff --git a/test/OpenApiTests/RestrictedControllers/ReadOnlyResourceChannel.cs b/test/OpenApiTests/RestrictedControllers/ReadOnlyResourceChannel.cs new file mode 100644 index 0000000000..483a83b0d6 --- /dev/null +++ b/test/OpenApiTests/RestrictedControllers/ReadOnlyResourceChannel.cs @@ -0,0 +1,12 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.RestrictedControllers; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.RestrictedControllers", GenerateControllerEndpoints = ControllerEndpoints)] +public sealed class ReadOnlyResourceChannel : Channel +{ + internal const JsonApiEndpoints ControllerEndpoints = JsonApiEndpoints.GetCollection | JsonApiEndpoints.GetSingle | JsonApiEndpoints.GetSecondary; +} diff --git a/test/OpenApiTests/RestrictedControllers/RelationshipChannel.cs b/test/OpenApiTests/RestrictedControllers/RelationshipChannel.cs new file mode 100644 index 0000000000..f24b900af0 --- /dev/null +++ b/test/OpenApiTests/RestrictedControllers/RelationshipChannel.cs @@ -0,0 +1,13 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.RestrictedControllers; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.RestrictedControllers", GenerateControllerEndpoints = ControllerEndpoints)] +public sealed class RelationshipChannel : Channel +{ + internal const JsonApiEndpoints ControllerEndpoints = JsonApiEndpoints.GetRelationship | JsonApiEndpoints.PostRelationship | + JsonApiEndpoints.PatchRelationship | JsonApiEndpoints.DeleteRelationship; +} diff --git a/test/OpenApiTests/RestrictedControllers/RestrictionDbContext.cs b/test/OpenApiTests/RestrictedControllers/RestrictionDbContext.cs new file mode 100644 index 0000000000..65173856aa --- /dev/null +++ b/test/OpenApiTests/RestrictedControllers/RestrictionDbContext.cs @@ -0,0 +1,16 @@ +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; +using TestBuildingBlocks; + +namespace OpenApiTests.RestrictedControllers; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public sealed class RestrictionDbContext(DbContextOptions options) + : TestableDbContext(options) +{ + public DbSet DataStreams => Set(); + public DbSet ReadOnlyChannels => Set(); + public DbSet WriteOnlyChannels => Set(); + public DbSet RelationshipChannels => Set(); + public DbSet ReadOnlyResourceChannels => Set(); +} diff --git a/test/OpenApiTests/RestrictedControllers/RestrictionFakers.cs b/test/OpenApiTests/RestrictedControllers/RestrictionFakers.cs new file mode 100644 index 0000000000..f1d97e8d4a --- /dev/null +++ b/test/OpenApiTests/RestrictedControllers/RestrictionFakers.cs @@ -0,0 +1,53 @@ +using Bogus; +using JetBrains.Annotations; +using TestBuildingBlocks; + +// @formatter:wrap_chained_method_calls chop_if_long +// @formatter:wrap_before_first_method_call true + +namespace OpenApiTests.RestrictedControllers; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +public sealed class RestrictionFakers +{ + private static readonly bool?[] NullableBooleanValues = + [ + true, + false, + null + ]; + + private readonly Lazy> _lazyDataStreamFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(stream => stream.BytesTransmitted, faker => (ulong)faker.Random.Long(0))); + + private readonly Lazy> _lazyReadOnlyChannelFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(channel => channel.Name, faker => faker.Lorem.Word()) + .RuleFor(channel => channel.IsCommercial, faker => faker.PickRandom(NullableBooleanValues)) + .RuleFor(channel => channel.IsAdultOnly, faker => faker.PickRandom(NullableBooleanValues))); + + private readonly Lazy> _lazyWriteOnlyChannelFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(channel => channel.Name, faker => faker.Lorem.Word()) + .RuleFor(channel => channel.IsCommercial, faker => faker.PickRandom(NullableBooleanValues)) + .RuleFor(channel => channel.IsAdultOnly, faker => faker.PickRandom(NullableBooleanValues))); + + private readonly Lazy> _lazyRelationshipChannelFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(channel => channel.Name, faker => faker.Lorem.Word()) + .RuleFor(channel => channel.IsCommercial, faker => faker.PickRandom(NullableBooleanValues)) + .RuleFor(channel => channel.IsAdultOnly, faker => faker.PickRandom(NullableBooleanValues))); + + private readonly Lazy> _lazyReadOnlyResourceChannelFaker = new(() => new Faker() + .MakeDeterministic() + .RuleFor(channel => channel.Name, faker => faker.Lorem.Word()) + .RuleFor(channel => channel.IsCommercial, faker => faker.PickRandom(NullableBooleanValues)) + .RuleFor(channel => channel.IsAdultOnly, faker => faker.PickRandom(NullableBooleanValues))); + + public Faker DataStream => _lazyDataStreamFaker.Value; + public Faker ReadOnlyChannel => _lazyReadOnlyChannelFaker.Value; + public Faker WriteOnlyChannel => _lazyWriteOnlyChannelFaker.Value; + public Faker RelationshipChannel => _lazyRelationshipChannelFaker.Value; + public Faker ReadOnlyResourceChannel => _lazyReadOnlyResourceChannelFaker.Value; +} diff --git a/test/OpenApiTests/RestrictedControllers/RestrictionTests.cs b/test/OpenApiTests/RestrictedControllers/RestrictionTests.cs new file mode 100644 index 0000000000..061b6b4733 --- /dev/null +++ b/test/OpenApiTests/RestrictedControllers/RestrictionTests.cs @@ -0,0 +1,62 @@ +using System.Collections.ObjectModel; +using System.Text.Json; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using Microsoft.Extensions.DependencyInjection; +using TestBuildingBlocks; +using Xunit; +using Xunit.Abstractions; + +namespace OpenApiTests.RestrictedControllers; + +public sealed class RestrictionTests : IClassFixture, RestrictionDbContext>> +{ + private readonly OpenApiTestContext, RestrictionDbContext> _testContext; + + public RestrictionTests(OpenApiTestContext, RestrictionDbContext> testContext, ITestOutputHelper testOutputHelper) + { + _testContext = testContext; + + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + testContext.UseController(); + + testContext.SetTestOutputHelper(testOutputHelper); + testContext.SwaggerDocumentOutputDirectory = $"{GetType().Namespace!.Replace('.', '/')}/GeneratedSwagger"; + } + + [Theory] + [InlineData(typeof(DataStream), JsonApiEndpoints.GetCollection | JsonApiEndpoints.GetSingle)] + [InlineData(typeof(ReadOnlyChannel), ReadOnlyChannel.ControllerEndpoints)] + [InlineData(typeof(WriteOnlyChannel), WriteOnlyChannel.ControllerEndpoints)] + [InlineData(typeof(RelationshipChannel), RelationshipChannel.ControllerEndpoints)] + [InlineData(typeof(ReadOnlyResourceChannel), ReadOnlyResourceChannel.ControllerEndpoints)] + public async Task Only_expected_endpoints_are_exposed(Type resourceClrType, JsonApiEndpoints expected) + { + // Arrange + var resourceGraph = _testContext.Factory.Services.GetRequiredService(); + ResourceType resourceType = resourceGraph.GetResourceType(resourceClrType); + IReadOnlyDictionary> endpointToPathMap = JsonPathBuilder.GetEndpointPaths(resourceType); + + // Act + JsonElement document = await _testContext.GetSwaggerDocumentAsync(); + + // Assert + string[] pathsExpected = JsonPathBuilder.KnownEndpoints.Where(endpoint => expected.HasFlag(endpoint)) + .SelectMany(endpoint => endpointToPathMap[endpoint]).ToArray(); + + string[] pathsNotExpected = endpointToPathMap.Values.SelectMany(paths => paths).Except(pathsExpected).ToArray(); + + foreach (string path in pathsExpected) + { + document.Should().ContainPath(path); + } + + foreach (string path in pathsNotExpected) + { + document.Should().NotContainPath(path); + } + } +} diff --git a/test/OpenApiTests/RestrictedControllers/WriteOnlyChannel.cs b/test/OpenApiTests/RestrictedControllers/WriteOnlyChannel.cs new file mode 100644 index 0000000000..75c576fb87 --- /dev/null +++ b/test/OpenApiTests/RestrictedControllers/WriteOnlyChannel.cs @@ -0,0 +1,12 @@ +using JetBrains.Annotations; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Resources.Annotations; + +namespace OpenApiTests.RestrictedControllers; + +[UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "OpenApiTests.RestrictedControllers", GenerateControllerEndpoints = ControllerEndpoints)] +public sealed class WriteOnlyChannel : Channel +{ + internal const JsonApiEndpoints ControllerEndpoints = JsonApiEndpoints.Command; +} diff --git a/test/SourceGeneratorTests/SourceCodeBuilder.cs b/test/SourceGeneratorTests/SourceCodeBuilder.cs index 05bdc031a4..7ecc02cbba 100644 --- a/test/SourceGeneratorTests/SourceCodeBuilder.cs +++ b/test/SourceGeneratorTests/SourceCodeBuilder.cs @@ -12,7 +12,7 @@ public string Build() { StringBuilder builder = new(); - if (_namespaceImports.Any()) + if (_namespaceImports.Count > 0) { foreach (string namespaceImport in _namespaceImports) { diff --git a/test/SourceGeneratorTests/SourceGeneratorTests.csproj b/test/SourceGeneratorTests/SourceGeneratorTests.csproj index e28bdc20d1..4f487fa168 100644 --- a/test/SourceGeneratorTests/SourceGeneratorTests.csproj +++ b/test/SourceGeneratorTests/SourceGeneratorTests.csproj @@ -1,6 +1,6 @@ - net8.0;net6.0 + net9.0;net8.0 diff --git a/test/TestBuildingBlocks/CapturingLoggerProvider.cs b/test/TestBuildingBlocks/CapturingLoggerProvider.cs new file mode 100644 index 0000000000..07366f5db1 --- /dev/null +++ b/test/TestBuildingBlocks/CapturingLoggerProvider.cs @@ -0,0 +1,121 @@ +using JetBrains.Annotations; +using Microsoft.Extensions.Logging; + +namespace TestBuildingBlocks; + +[PublicAPI] +public sealed class CapturingLoggerProvider : ILoggerProvider +{ + private static readonly Func DefaultFilter = (_, _) => true; + private readonly Func _filter; + +#if NET8_0 + private readonly object _lockObject = new(); +#else + private readonly Lock _lockObject = new(); +#endif + private readonly List _messages = []; + + public CapturingLoggerProvider() + : this(DefaultFilter) + { + } + + public CapturingLoggerProvider(LogLevel minimumLevel) + : this((_, logLevel) => logLevel != LogLevel.None && logLevel >= minimumLevel) + { + } + + public CapturingLoggerProvider(Func filter) + { + ArgumentNullException.ThrowIfNull(filter); + + _filter = filter; + } + + public ILogger CreateLogger(string categoryName) + { + ArgumentException.ThrowIfNullOrEmpty(categoryName); + + return new CapturingLogger(this, categoryName, _filter); + } + + public void Clear() + { + lock (_lockObject) + { + _messages.Clear(); + } + } + + public IReadOnlyList GetMessages() + { + LogMessage[] snapshot; + + lock (_lockObject) + { + snapshot = _messages.ToArray(); + } + + return snapshot.AsReadOnly(); + } + + public IReadOnlyList GetLines() + { + IReadOnlyList snapshot = GetMessages(); + return snapshot.Select(message => message.ToString()).ToArray().AsReadOnly(); + } + + private void Add(LogMessage message) + { + lock (_lockObject) + { + _messages.Add(message); + } + } + + public void Dispose() + { + } + + private sealed class CapturingLogger(CapturingLoggerProvider owner, string categoryName, Func filter) : ILogger + { + private readonly CapturingLoggerProvider _owner = owner; + private readonly string _categoryName = categoryName; + private readonly Func _filter = filter; + + public bool IsEnabled(LogLevel logLevel) + { + return _filter(_categoryName, logLevel); + } + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) + { + if (IsEnabled(logLevel)) + { + string text = formatter(state, exception); + var message = new LogMessage(logLevel, _categoryName, text); + _owner.Add(message); + } + } + + public IDisposable BeginScope(TState state) + where TState : notnull + { + return NullScope.Instance; + } + + private sealed class NullScope : IDisposable + { + public static readonly NullScope Instance = new(); + + private NullScope() + { + } + + public void Dispose() + { + } + } + } +} diff --git a/test/TestBuildingBlocks/FakeLoggerFactory.cs b/test/TestBuildingBlocks/FakeLoggerFactory.cs deleted file mode 100644 index cb726bb4d7..0000000000 --- a/test/TestBuildingBlocks/FakeLoggerFactory.cs +++ /dev/null @@ -1,90 +0,0 @@ -using JetBrains.Annotations; -using Microsoft.Extensions.Logging; - -namespace TestBuildingBlocks; - -[PublicAPI] -public sealed class FakeLoggerFactory(LogLevel minimumLevel) : ILoggerFactory, ILoggerProvider -{ - public FakeLogger Logger { get; } = new(minimumLevel); - - public ILogger CreateLogger(string categoryName) - { - return Logger; - } - - public void AddProvider(ILoggerProvider provider) - { - } - - public void Dispose() - { - } - - public sealed class FakeLogger(LogLevel minimumLevel) : ILogger - { - private readonly LogLevel _minimumLevel = minimumLevel; - - private readonly object _lockObject = new(); - private readonly List _messages = []; - - public bool IsEnabled(LogLevel logLevel) - { - return _minimumLevel != LogLevel.None && logLevel >= _minimumLevel; - } - - public void Clear() - { - lock (_lockObject) - { - _messages.Clear(); - } - } - - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) - { - if (IsEnabled(logLevel)) - { - string message = formatter(state, exception); - - lock (_lockObject) - { - _messages.Add(new FakeLogMessage(logLevel, message)); - } - } - } - - public IDisposable BeginScope(TState state) - where TState : notnull - { - return NullScope.Instance; - } - - public IReadOnlyList GetMessages() - { - lock (_lockObject) - { - List snapshot = _messages.ToList(); - return snapshot.AsReadOnly(); - } - } - - public IReadOnlyList GetLines() - { - return GetMessages().Select(message => message.ToString()).ToArray(); - } - - private sealed class NullScope : IDisposable - { - public static readonly NullScope Instance = new(); - - private NullScope() - { - } - - public void Dispose() - { - } - } - } -} diff --git a/test/TestBuildingBlocks/FakerExtensions.cs b/test/TestBuildingBlocks/FakerExtensions.cs index 282aa26c6b..b6cb073e8c 100644 --- a/test/TestBuildingBlocks/FakerExtensions.cs +++ b/test/TestBuildingBlocks/FakerExtensions.cs @@ -7,7 +7,7 @@ namespace TestBuildingBlocks; public static class FakerExtensions { - public static Faker MakeDeterministic(this Faker faker) + public static Faker MakeDeterministic(this Faker faker, DateTime? systemTimeUtc = null) where T : class { int seed = GetFakerSeed(); @@ -15,12 +15,14 @@ public static Faker MakeDeterministic(this Faker faker) // Setting the system DateTime to kind Utc, so that faker calls like PastOffset() don't depend on the system time zone. // See https://docs.microsoft.com/en-us/dotnet/api/system.datetimeoffset.op_implicit?view=net-6.0#remarks - faker.UseDateTimeReference(FrozenSystemClock.DefaultDateTimeUtc); + faker.UseDateTimeReference(systemTimeUtc ?? IntegrationTest.DefaultDateTimeUtc.UtcDateTime); return faker; } - private static int GetFakerSeed() +#pragma warning disable AV1008 // Class should not be static + public static int GetFakerSeed() +#pragma warning restore AV1008 // Class should not be static { // The goal here is to have stable data over multiple test runs, but at the same time different data per test case. @@ -79,4 +81,34 @@ private static int GetDeterministicHashCode(string source) return hash1 + hash2 * 1566083941; } } + + // The methods below exist so that a non-nullable return type is inferred. + // The Bogus NuGet package is not annotated for nullable reference types. + + public static T GenerateOne(this Faker faker) + where T : class + { + return faker.Generate(); + } + +#pragma warning disable AV1130 // Return type in method signature should be an interface to an unchangeable collection + public static List GenerateList(this Faker faker, int count) + where T : class + { + return faker.Generate(count); + } + + public static HashSet GenerateSet(this Faker faker, int count) + where T : class + { + return faker.Generate(count).ToHashSet(); + } + + public static HashSet GenerateSet(this Faker faker, int count) + where TOut : class + where TIn : class, TOut + { + return faker.Generate(count).Cast().ToHashSet(); + } +#pragma warning restore AV1130 // Return type in method signature should be an interface to an unchangeable collection } diff --git a/test/TestBuildingBlocks/ObjectAssertionsExtensions.cs b/test/TestBuildingBlocks/FluentExtensions.cs similarity index 54% rename from test/TestBuildingBlocks/ObjectAssertionsExtensions.cs rename to test/TestBuildingBlocks/FluentExtensions.cs index ee2be771e1..1061a71765 100644 --- a/test/TestBuildingBlocks/ObjectAssertionsExtensions.cs +++ b/test/TestBuildingBlocks/FluentExtensions.cs @@ -6,11 +6,13 @@ using FluentAssertions.Numeric; using FluentAssertions.Primitives; using JetBrains.Annotations; +using SysNotNull = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +// ReSharper disable UnusedMethodReturnValue.Global namespace TestBuildingBlocks; -[PublicAPI] -public static class ObjectAssertionsExtensions +public static class FluentExtensions { private const decimal NumericPrecision = 0.00000000001M; @@ -60,19 +62,49 @@ public static void BeJson(this StringAssertions source, string expected, string private static string ToJsonString(JsonDocument document) { using var stream = new MemoryStream(); - var writer = new Utf8JsonWriter(stream, JsonWriterOptions); - document.WriteTo(writer); - writer.Flush(); + using (var writer = new Utf8JsonWriter(stream, JsonWriterOptions)) + { + document.WriteTo(writer); + } + return Encoding.UTF8.GetString(stream.ToArray()); } - /// - /// Asserts that a "meta" dictionary contains a single element named "total" with the specified value. - /// - [CustomAssertion] - public static void ContainTotal(this GenericDictionaryAssertions, string, object?> source, int expectedTotal) + // Workaround for source.Should().NotBeNull().And.Subject having declared type 'object'. + [System.Diagnostics.Contracts.Pure] + public static StrongReferenceTypeAssertions RefShould([SysNotNull] this T? actualValue) + where T : class + { + actualValue.Should().NotBeNull(); + return new StrongReferenceTypeAssertions(actualValue); + } + + public static AndConstraint OnlyContainKeys( + this GenericDictionaryAssertions source, params TKey[] expected) + where TCollection : IEnumerable> + where TAssertions : GenericDictionaryAssertions + { + return source.HaveCount(expected.Length).And.ContainKeys(expected); + } + + // Workaround for CS0854: An expression tree may not contain a call or invocation that uses optional arguments. + public static WhoseValueConstraint ContainKey2( + this GenericDictionaryAssertions source, TKey expected) + where TCollection : IEnumerable> + where TAssertions : GenericDictionaryAssertions + { + return source.ContainKey(expected); + } + + public static void With(this T subject, [InstantHandle] Action continuation) + { + continuation(subject); + } + + public sealed class StrongReferenceTypeAssertions(TReference subject) + : ReferenceTypeAssertions>(subject) { - source.ContainKey("total").WhoseValue.Should().BeOfType().Subject.GetInt32().Should().Be(expectedTotal); + protected override string Identifier => "subject"; } } diff --git a/test/TestBuildingBlocks/FluentJsonElementExtensions.cs b/test/TestBuildingBlocks/FluentJsonElementExtensions.cs new file mode 100644 index 0000000000..76610ee881 --- /dev/null +++ b/test/TestBuildingBlocks/FluentJsonElementExtensions.cs @@ -0,0 +1,156 @@ +using System.Text.Json; +using BlushingPenguin.JsonPath; +using FluentAssertions; +using FluentAssertions.Execution; +using JetBrains.Annotations; + +namespace TestBuildingBlocks; + +public static class FluentJsonElementExtensions +{ + private const string ComponentSchemaPrefix = "#/components/schemas/"; + + public static JsonElementAssertions Should(this JsonElement source) + { + return new JsonElementAssertions(source); + } + + [CustomAssertion] + public static SchemaReferenceIdContainer ShouldBeSchemaReferenceId(this JsonElement source, string value) + { + string schemaReferenceId = GetSchemaReferenceId(source); + schemaReferenceId.Should().Be(value); + + return new SchemaReferenceIdContainer(value); + } + + [CustomAssertion] + public static string GetSchemaReferenceId(this JsonElement source) + { + source.ValueKind.Should().Be(JsonValueKind.String); + + string? jsonElementValue = source.GetString(); + jsonElementValue.Should().StartWith(ComponentSchemaPrefix); + + return jsonElementValue[ComponentSchemaPrefix.Length..]; + } + + [CustomAssertion] + public static void WithSchemaReferenceId(this JsonElement subject, [InstantHandle] Action continuation) + { + string schemaReferenceId = GetSchemaReferenceId(subject); + + continuation(schemaReferenceId); + } + + public sealed class SchemaReferenceIdContainer + { + public string SchemaReferenceId { get; } + + internal SchemaReferenceIdContainer(string schemaReferenceId) + { + SchemaReferenceId = schemaReferenceId; + } + } + + public sealed class JsonElementAssertions : JsonElementAssertions + { + internal JsonElementAssertions(JsonElement subject) + : base(subject) + { + } + } + + public class JsonElementAssertions + where TAssertions : JsonElementAssertions + { + private readonly JsonElement _subject; + + protected JsonElementAssertions(JsonElement subject) + { + _subject = subject; + } + + public void ContainProperty(string propertyName) + { + string json = _subject.ToString(); + string escapedJson = json.Replace("{", "{{").Replace("}", "}}"); + + Execute.Assertion.ForCondition(_subject.TryGetProperty(propertyName, out _)) + .FailWith($"Expected JSON element '{escapedJson}' to contain a property named '{propertyName}'."); + } + + public JsonElement ContainPath(string jsonPath) + { + Func elementSelector = () => _subject.SelectToken(jsonPath, true)!.Value; + return elementSelector.Should().NotThrow().Subject; + } + + public void NotContainPath(string jsonPath) + { + JsonElement? pathToken = _subject.SelectToken(jsonPath); + pathToken.Should().BeNull(); + } + + public void Be(object? value) + { + if (value == null) + { + _subject.ValueKind.Should().Be(JsonValueKind.Null); + } + else if (value is bool boolValue) + { + _subject.ValueKind.Should().Be(boolValue ? JsonValueKind.True : JsonValueKind.False); + } + else if (value is int intValue) + { + _subject.ValueKind.Should().Be(JsonValueKind.Number); + _subject.GetInt32().Should().Be(intValue); + } + else if (value is double doubleValue) + { + _subject.ValueKind.Should().Be(JsonValueKind.Number); + _subject.GetDouble().Should().Be(doubleValue); + } + else if (value is string stringValue) + { + _subject.ValueKind.Should().Be(JsonValueKind.String); + _subject.GetString().Should().Be(stringValue); + } + else + { + throw new NotSupportedException($"Unknown object of type '{value.GetType()}'."); + } + } + + public void HaveProperty(string jsonPath, object? propertyValue) + { + _subject.Should().ContainPath(jsonPath).With(element => element.Should().Be(propertyValue)); + } + + public void ContainArrayElement(string value) + { + _subject.ValueKind.Should().Be(JsonValueKind.Array); + + string?[] stringValues = _subject.EnumerateArray().Where(element => element.ValueKind == JsonValueKind.String) + .Select(element => element.GetString()).ToArray(); + + stringValues.Should().Contain(value); + } + + public void NotContainArrayElement(string value) + { + _subject.ValueKind.Should().Be(JsonValueKind.Array); + + string?[] stringValues = _subject.EnumerateArray().Where(element => element.ValueKind == JsonValueKind.String) + .Select(element => element.GetString()).ToArray(); + + stringValues.Should().NotContain(value); + } + + public void BeJson(string json) + { + _subject.ToString().Should().BeJson(json); + } + } +} diff --git a/test/TestBuildingBlocks/FluentMetaExtensions.cs b/test/TestBuildingBlocks/FluentMetaExtensions.cs new file mode 100644 index 0000000000..ff81bb47f0 --- /dev/null +++ b/test/TestBuildingBlocks/FluentMetaExtensions.cs @@ -0,0 +1,69 @@ +using System.Text.Json; +using FluentAssertions; +using FluentAssertions.Collections; + +namespace TestBuildingBlocks; + +public static class FluentMetaExtensions +{ + /// + /// Asserts that a "meta" dictionary contains a single element named "total" with the specified value. + /// + [CustomAssertion] +#pragma warning disable AV1553 // Do not use optional parameters with default value null for strings, collections or tasks + public static void ContainTotal(this GenericDictionaryAssertions, string, object?> source, int expected, + string? keyName = null) +#pragma warning restore AV1553 // Do not use optional parameters with default value null for strings, collections or tasks + { + JsonElement element = GetMetaJsonElement(source, keyName ?? "total"); + element.GetInt32().Should().Be(expected); + } + + /// + /// Asserts that a "meta" dictionary contains a single element named "requestBody" that isn't empty. + /// + [CustomAssertion] + public static void HaveRequestBody(this GenericDictionaryAssertions, string, object?> source) + { + JsonElement element = GetMetaJsonElement(source, "requestBody"); + element.ToString().Should().NotBeEmpty(); + } + + /// + /// Asserts that a "meta" dictionary contains a single element named "requestBody" with the specified value. + /// + [CustomAssertion] + public static void ContainRequestBody(this GenericDictionaryAssertions, string, object?> source, string expected) + { + JsonElement element = GetMetaJsonElement(source, "requestBody"); + element.GetString().Should().Be(expected); + } + + /// + /// Asserts that a "meta" dictionary contains a single element named "stackTrace" that isn't empty. + /// + [CustomAssertion] + public static void HaveStackTrace(this GenericDictionaryAssertions, string, object?> source) + { + JsonElement element = GetMetaJsonElement(source, "stackTrace"); + IEnumerable stackTraceLines = element.EnumerateArray().Select(token => token.GetString()); + stackTraceLines.Should().NotBeEmpty(); + } + + /// + /// Asserts that a "meta" dictionary contains a single element named "stackTrace" that contains the specified pattern. + /// + [CustomAssertion] + public static void HaveInStackTrace(this GenericDictionaryAssertions, string, object?> source, string pattern) + { + JsonElement element = GetMetaJsonElement(source, "stackTrace"); + IEnumerable stackTraceLines = element.EnumerateArray().Select(token => token.GetString()); + stackTraceLines.Should().ContainMatch(pattern); + } + + private static JsonElement GetMetaJsonElement(GenericDictionaryAssertions, string, object?> source, string metaKey) + { + object? value = source.ContainKey(metaKey).WhoseValue; + return value.Should().BeOfType().Subject; + } +} diff --git a/test/TestBuildingBlocks/FrozenSystemClock.cs b/test/TestBuildingBlocks/FrozenSystemClock.cs deleted file mode 100644 index 031349086d..0000000000 --- a/test/TestBuildingBlocks/FrozenSystemClock.cs +++ /dev/null @@ -1,11 +0,0 @@ -using FluentAssertions.Extensions; - -namespace TestBuildingBlocks; - -public sealed class FrozenSystemClock : ISystemClock -{ - internal static readonly DateTime DefaultDateTimeUtc = 1.January(2020).At(1, 1, 1).AsUtc(); - public static readonly DateTimeOffset DefaultDateTimeOffsetUtc = DefaultDateTimeUtc; - - public DateTimeOffset UtcNow { get; set; } = DefaultDateTimeOffsetUtc; -} diff --git a/test/TestBuildingBlocks/FrozenTimeProvider.cs b/test/TestBuildingBlocks/FrozenTimeProvider.cs new file mode 100644 index 0000000000..7b237eb00e --- /dev/null +++ b/test/TestBuildingBlocks/FrozenTimeProvider.cs @@ -0,0 +1,44 @@ +using System.Globalization; + +namespace TestBuildingBlocks; + +public sealed class FrozenTimeProvider(DateTimeOffset startDateTime, TimeZoneInfo? localTimeZone = null) : TimeProvider +{ + private readonly DateTimeOffset _startDateTime = startDateTime; + private readonly TimeZoneInfo? _localTimeZone = localTimeZone; + + private DateTimeOffset _dateTime = startDateTime; + + public override TimeZoneInfo LocalTimeZone => _localTimeZone ?? throw new NotSupportedException(); + public override long TimestampFrequency => throw new NotSupportedException(); + + public override DateTimeOffset GetUtcNow() + { + return _dateTime; + } + + public void SetUtcNow(DateTimeOffset value) + { + _dateTime = value; + } + + public void Reset() + { + _dateTime = _startDateTime; + } + + public override ITimer CreateTimer(TimerCallback callback, object? state, TimeSpan dueTime, TimeSpan period) + { + throw new NotSupportedException(); + } + + public override long GetTimestamp() + { + throw new NotSupportedException(); + } + + public override string ToString() + { + return _dateTime.ToString("yyyy-MM-ddTHH:mm:ss.fff", CultureInfo.InvariantCulture); + } +} diff --git a/test/TestBuildingBlocks/HttpRequestHeadersExtensions.cs b/test/TestBuildingBlocks/HttpRequestHeadersExtensions.cs new file mode 100644 index 0000000000..8a784ec759 --- /dev/null +++ b/test/TestBuildingBlocks/HttpRequestHeadersExtensions.cs @@ -0,0 +1,16 @@ +using System.Net.Http.Headers; +using Microsoft.Extensions.Primitives; + +namespace TestBuildingBlocks; + +public static class HttpRequestHeadersExtensions +{ + /// + /// Returns the value of the specified HTTP request header, or null when not found. If the header occurs multiple times, their values are + /// collapsed into a comma-separated string, without changing any surrounding double quotes. + /// + public static string? GetValue(this HttpRequestHeaders requestHeaders, string name) + { + return requestHeaders.TryGetValues(name, out IEnumerable? values) ? new StringValues(values.ToArray()).ToString() : null; + } +} diff --git a/test/TestBuildingBlocks/ISystemClock.cs b/test/TestBuildingBlocks/ISystemClock.cs deleted file mode 100644 index eb1c8628a3..0000000000 --- a/test/TestBuildingBlocks/ISystemClock.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace TestBuildingBlocks; - -public interface ISystemClock -{ - DateTimeOffset UtcNow { get; } -} diff --git a/test/TestBuildingBlocks/IntegrationTest.cs b/test/TestBuildingBlocks/IntegrationTest.cs index 73ced10d8d..0b94ac7448 100644 --- a/test/TestBuildingBlocks/IntegrationTest.cs +++ b/test/TestBuildingBlocks/IntegrationTest.cs @@ -1,6 +1,7 @@ using System.Net.Http.Headers; using System.Text; using System.Text.Json; +using FluentAssertions.Extensions; using JsonApiDotNetCore.Middleware; using Xunit; @@ -12,14 +13,21 @@ namespace TestBuildingBlocks; /// public abstract class IntegrationTest : IAsyncLifetime { - private static readonly SemaphoreSlim ThrottleSemaphore; + private static readonly MediaTypeHeaderValue DefaultMediaType = MediaTypeHeaderValue.Parse(JsonApiMediaType.Default.ToString()); + + private static readonly MediaTypeWithQualityHeaderValue OperationsMediaType = + MediaTypeWithQualityHeaderValue.Parse(JsonApiMediaType.AtomicOperations.ToString()); + + private static readonly SemaphoreSlim ThrottleSemaphore = GetDefaultThrottleSemaphore(); + + public static DateTimeOffset DefaultDateTimeUtc { get; } = 1.January(2020).At(1, 2, 3).AsUtc(); protected abstract JsonSerializerOptions SerializerOptions { get; } - static IntegrationTest() + private static SemaphoreSlim GetDefaultThrottleSemaphore() { int maxConcurrentTestRuns = OperatingSystem.IsWindows() && Environment.GetEnvironmentVariable("CI") != null ? 32 : 64; - ThrottleSemaphore = new SemaphoreSlim(maxConcurrentTestRuns); + return new SemaphoreSlim(maxConcurrentTestRuns); } public async Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecuteHeadAsync(string requestUrl, @@ -34,32 +42,38 @@ static IntegrationTest() return await ExecuteRequestAsync(HttpMethod.Get, requestUrl, null, null, setRequestHeaders); } +#pragma warning disable AV1553 // Do not use optional parameters with default value null for strings, collections or tasks public async Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecutePostAsync(string requestUrl, - object requestBody, string contentType = HeaderConstants.MediaType, Action? setRequestHeaders = null) + object requestBody, string? contentType = null, Action? setRequestHeaders = null) +#pragma warning restore AV1553 // Do not use optional parameters with default value null for strings, collections or tasks { - return await ExecuteRequestAsync(HttpMethod.Post, requestUrl, requestBody, contentType, setRequestHeaders); + MediaTypeHeaderValue mediaType = contentType == null ? DefaultMediaType : MediaTypeHeaderValue.Parse(contentType); + + return await ExecuteRequestAsync(HttpMethod.Post, requestUrl, requestBody, mediaType, setRequestHeaders); } public async Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecutePostAtomicAsync(string requestUrl, - object requestBody, string contentType = HeaderConstants.AtomicOperationsMediaType, Action? setRequestHeaders = null) + object requestBody) { - return await ExecuteRequestAsync(HttpMethod.Post, requestUrl, requestBody, contentType, setRequestHeaders); + Action setRequestHeaders = headers => headers.Accept.Add(OperationsMediaType); + + return await ExecuteRequestAsync(HttpMethod.Post, requestUrl, requestBody, OperationsMediaType, setRequestHeaders); } public async Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecutePatchAsync(string requestUrl, - object requestBody, string contentType = HeaderConstants.MediaType, Action? setRequestHeaders = null) + object requestBody, Action? setRequestHeaders = null) { - return await ExecuteRequestAsync(HttpMethod.Patch, requestUrl, requestBody, contentType, setRequestHeaders); + return await ExecuteRequestAsync(HttpMethod.Patch, requestUrl, requestBody, DefaultMediaType, setRequestHeaders); } public async Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecuteDeleteAsync(string requestUrl, - object? requestBody = null, string contentType = HeaderConstants.MediaType, Action? setRequestHeaders = null) + object? requestBody = null, Action? setRequestHeaders = null) { - return await ExecuteRequestAsync(HttpMethod.Delete, requestUrl, requestBody, contentType, setRequestHeaders); + return await ExecuteRequestAsync(HttpMethod.Delete, requestUrl, requestBody, DefaultMediaType, setRequestHeaders); } private async Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecuteRequestAsync(HttpMethod method, - string requestUrl, object? requestBody, string? contentType, Action? setRequestHeaders) + string requestUrl, object? requestBody, MediaTypeHeaderValue? contentType, Action? setRequestHeaders) { using var request = new HttpRequestMessage(method, requestUrl); string? requestText = SerializeRequest(requestBody); @@ -72,7 +86,7 @@ static IntegrationTest() if (contentType != null) { - request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(contentType); + request.Content.Headers.ContentType = contentType; } } diff --git a/test/TestBuildingBlocks/IntegrationTestContext.cs b/test/TestBuildingBlocks/IntegrationTestContext.cs index 83f00667b2..4876388c3a 100644 --- a/test/TestBuildingBlocks/IntegrationTestContext.cs +++ b/test/TestBuildingBlocks/IntegrationTestContext.cs @@ -9,6 +9,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; @@ -34,6 +35,7 @@ public class IntegrationTestContext : IntegrationTest private readonly TestControllerProvider _testControllerProvider = new(); private Action? _loggingConfiguration; private Action? _configureServices; + private Action? _postConfigureServices; protected override JsonSerializerOptions SerializerOptions { @@ -74,6 +76,8 @@ private WebApplicationFactory CreateFactory() { _configureServices?.Invoke(services); + services.Replace(ServiceDescriptor.Singleton(new FrozenTimeProvider(DefaultDateTimeUtc))); + services.ReplaceControllers(_testControllerProvider); services.AddDbContext(options => @@ -83,16 +87,13 @@ private WebApplicationFactory CreateFactory() }); }); - // We have placed an appsettings.json in the TestBuildingBlocks project directory and set the content root to there. Note that - // controllers are not discovered in the content root, but are registered manually using IntegrationTestContext.UseController. - WebApplicationFactory factoryWithConfiguredContentRoot = - factory.WithWebHostBuilder(builder => builder.UseSolutionRelativeContentRoot($"test/{nameof(TestBuildingBlocks)}")); + factory.PostConfigureServices(_postConfigureServices); - using IServiceScope scope = factoryWithConfiguredContentRoot.Services.CreateScope(); + using IServiceScope scope = factory.Services.CreateScope(); var dbContext = scope.ServiceProvider.GetRequiredService(); dbContext.Database.EnsureCreated(); - return factoryWithConfiguredContentRoot; + return factory; } [Conditional("DEBUG")] @@ -105,14 +106,34 @@ private static void SetDbContextDebugOptions(DbContextOptionsBuilder options) public void ConfigureLogging(Action loggingConfiguration) { + if (_loggingConfiguration != null && _loggingConfiguration != loggingConfiguration) + { + throw new InvalidOperationException($"Do not call {nameof(ConfigureLogging)} multiple times."); + } + _loggingConfiguration = loggingConfiguration; } public void ConfigureServices(Action configureServices) { + if (_configureServices != null && _configureServices != configureServices) + { + throw new InvalidOperationException($"Do not call {nameof(ConfigureServices)} multiple times."); + } + _configureServices = configureServices; } + public void PostConfigureServices(Action postConfigureServices) + { + if (_postConfigureServices != null && _postConfigureServices != postConfigureServices) + { + throw new InvalidOperationException($"Do not call {nameof(PostConfigureServices)} multiple times."); + } + + _postConfigureServices = postConfigureServices; + } + public async Task RunOnDatabaseAsync(Func asyncAction) { await using AsyncServiceScope scope = Factory.Services.CreateAsyncScope(); @@ -141,6 +162,7 @@ private sealed class IntegrationTestWebApplicationFactory : WebApplicationFactor { private Action? _loggingConfiguration; private Action? _configureServices; + private Action? _postConfigureServices; public void ConfigureLogging(Action? loggingConfiguration) { @@ -152,6 +174,18 @@ public void ConfigureServices(Action? configureServices) _configureServices = configureServices; } + public void PostConfigureServices(Action? configureServices) + { + _postConfigureServices = configureServices; + } + + protected override void ConfigureWebHost(IWebHostBuilder builder) + { + // We have placed an appsettings.json in the TestBuildingBlocks project directory and set the content root to there. Note that + // controllers are not discovered in the content root, but are registered manually using IntegrationTestContext.UseController. + builder.UseSolutionRelativeContentRoot($"test/{nameof(TestBuildingBlocks)}"); + } + protected override IHostBuilder CreateHostBuilder() { // @formatter:wrap_chained_method_calls chop_always @@ -172,6 +206,7 @@ protected override IHostBuilder CreateHostBuilder() { webBuilder.ConfigureServices(services => _configureServices?.Invoke(services)); webBuilder.UseStartup(); + webBuilder.ConfigureServices(services => _postConfigureServices?.Invoke(services)); }) .ConfigureLogging(options => _loggingConfiguration?.Invoke(options)); diff --git a/test/TestBuildingBlocks/JsonApiStringConverter.cs b/test/TestBuildingBlocks/JsonApiStringConverter.cs index faf26ef988..c20f115cf5 100644 --- a/test/TestBuildingBlocks/JsonApiStringConverter.cs +++ b/test/TestBuildingBlocks/JsonApiStringConverter.cs @@ -16,7 +16,7 @@ public static string ExtractErrorId(string responseBody) } catch (Exception exception) { - throw new Exception($"Failed to extract Error ID from response body '{responseBody}'.", exception); + throw new JsonException($"Failed to extract Error ID from response body '{responseBody}'.", exception); } } } diff --git a/test/TestBuildingBlocks/FakeLogMessage.cs b/test/TestBuildingBlocks/LogMessage.cs similarity index 69% rename from test/TestBuildingBlocks/FakeLogMessage.cs rename to test/TestBuildingBlocks/LogMessage.cs index cd6cc2bdaf..74d5552250 100644 --- a/test/TestBuildingBlocks/FakeLogMessage.cs +++ b/test/TestBuildingBlocks/LogMessage.cs @@ -4,9 +4,10 @@ namespace TestBuildingBlocks; [PublicAPI] -public sealed class FakeLogMessage(LogLevel logLevel, string text) +public sealed class LogMessage(LogLevel logLevel, string categoryName, string text) { public LogLevel LogLevel { get; } = logLevel; + public string CategoryName { get; } = categoryName; public string Text { get; } = text; public override string ToString() diff --git a/test/TestBuildingBlocks/LogOutputFields.cs b/test/TestBuildingBlocks/LogOutputFields.cs index 02ea580eff..c6a1475579 100644 --- a/test/TestBuildingBlocks/LogOutputFields.cs +++ b/test/TestBuildingBlocks/LogOutputFields.cs @@ -8,10 +8,12 @@ public enum LogOutputFields { None = 0, Level = 1, - Category = 1 << 1, - Message = 1 << 2, - Exception = 1 << 3, - Scopes = 1 << 4, + CategoryName = 1 << 1, + CategoryNamespace = 1 << 2, + Message = 1 << 3, + Exception = 1 << 4, + Scopes = 1 << 5, + Category = CategoryName | CategoryNamespace, All = Level | Category | Message | Exception | Scopes } diff --git a/test/TestBuildingBlocks/MarkedText.cs b/test/TestBuildingBlocks/MarkedText.cs index f0935b0c2a..003fd0a24f 100644 --- a/test/TestBuildingBlocks/MarkedText.cs +++ b/test/TestBuildingBlocks/MarkedText.cs @@ -1,6 +1,5 @@ using System.Diagnostics; using JetBrains.Annotations; -using JsonApiDotNetCore; namespace TestBuildingBlocks; @@ -14,7 +13,7 @@ public sealed class MarkedText public MarkedText(string source, char marker) { - ArgumentGuard.NotNull(source); + ArgumentNullException.ThrowIfNull(source); Source = source; Position = GetPositionFromMarker(marker); diff --git a/test/TestBuildingBlocks/NullabilityAssertionExtensions.cs b/test/TestBuildingBlocks/NullabilityAssertionExtensions.cs deleted file mode 100644 index 0627449664..0000000000 --- a/test/TestBuildingBlocks/NullabilityAssertionExtensions.cs +++ /dev/null @@ -1,62 +0,0 @@ -using FluentAssertions; -using JetBrains.Annotations; -using SysNotNull = System.Diagnostics.CodeAnalysis.NotNullAttribute; - -// ReSharper disable PossibleMultipleEnumeration -#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. - -namespace TestBuildingBlocks; - -public static class NullabilityAssertionExtensions -{ - [CustomAssertion] - public static T ShouldNotBeNull([SysNotNull] this T? subject) - { - subject.Should().NotBeNull(); - return subject!; - } - - [CustomAssertion] - public static void ShouldNotBeEmpty([SysNotNull] this string? subject) - { - subject.Should().NotBeEmpty(); - } - - [CustomAssertion] - public static void ShouldNotBeEmpty([SysNotNull] this IEnumerable? subject) - { - subject.Should().NotBeEmpty(); - } - - [CustomAssertion] - public static void ShouldNotBeNullOrEmpty([SysNotNull] this string? subject) - { - subject.Should().NotBeNullOrEmpty(); - } - - [CustomAssertion] - public static void ShouldHaveCount([SysNotNull] this IEnumerable? subject, int expected) - { - subject.Should().HaveCount(expected); - } - - [CustomAssertion] - public static TValue? ShouldContainKey([SysNotNull] this IDictionary? subject, TKey expected) - { - subject.Should().ContainKey(expected); - - return subject![expected]; - } - - [CustomAssertion] - public static void ShouldOnlyContainKeys([SysNotNull] this IDictionary? subject, params TKey[] expected) - { - subject.Should().HaveCount(expected.Length); - subject.Should().ContainKeys(expected); - } - - public static void With(this T subject, [InstantHandle] Action continuation) - { - continuation(subject); - } -} diff --git a/test/TestBuildingBlocks/AssemblyInfo.cs b/test/TestBuildingBlocks/Properties/AssemblyInfo.cs similarity index 100% rename from test/TestBuildingBlocks/AssemblyInfo.cs rename to test/TestBuildingBlocks/Properties/AssemblyInfo.cs diff --git a/test/TestBuildingBlocks/ServiceCollectionExtensions.cs b/test/TestBuildingBlocks/ServiceCollectionExtensions.cs index 2a11397f69..8e5102fa23 100644 --- a/test/TestBuildingBlocks/ServiceCollectionExtensions.cs +++ b/test/TestBuildingBlocks/ServiceCollectionExtensions.cs @@ -1,5 +1,4 @@ using System.Reflection; -using JsonApiDotNetCore; using Microsoft.AspNetCore.Mvc.ApplicationParts; using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.Extensions.DependencyInjection; @@ -10,7 +9,7 @@ internal static class ServiceCollectionExtensions { public static void ReplaceControllers(this IServiceCollection services, TestControllerProvider provider) { - ArgumentGuard.NotNull(services); + ArgumentNullException.ThrowIfNull(services); services.AddMvcCore().ConfigureApplicationPartManager(manager => { diff --git a/test/TestBuildingBlocks/TestBuildingBlocks.csproj b/test/TestBuildingBlocks/TestBuildingBlocks.csproj index ae6cf32ff6..3f16e3818e 100644 --- a/test/TestBuildingBlocks/TestBuildingBlocks.csproj +++ b/test/TestBuildingBlocks/TestBuildingBlocks.csproj @@ -1,6 +1,6 @@ - net8.0;net6.0 + net9.0;net8.0 @@ -10,6 +10,7 @@ + @@ -19,6 +20,6 @@ - + diff --git a/test/TestBuildingBlocks/TestControllerProvider.cs b/test/TestBuildingBlocks/TestControllerProvider.cs index 664fe34be1..4f183e50c1 100644 --- a/test/TestBuildingBlocks/TestControllerProvider.cs +++ b/test/TestBuildingBlocks/TestControllerProvider.cs @@ -5,9 +5,9 @@ namespace TestBuildingBlocks; internal sealed class TestControllerProvider : ControllerFeatureProvider { - private readonly ISet _allowedControllerTypes = new HashSet(); + private readonly HashSet _allowedControllerTypes = []; - internal ISet ControllerAssemblies { get; } = new HashSet(); + internal HashSet ControllerAssemblies { get; } = []; public void AddController(Type controller) { diff --git a/test/TestBuildingBlocks/TestableDbContext.cs b/test/TestBuildingBlocks/TestableDbContext.cs index a91a8530ad..1d8f884ba5 100644 --- a/test/TestBuildingBlocks/TestableDbContext.cs +++ b/test/TestBuildingBlocks/TestableDbContext.cs @@ -5,7 +5,8 @@ namespace TestBuildingBlocks; -public abstract class TestableDbContext(DbContextOptions options) : DbContext(options) +public abstract class TestableDbContext(DbContextOptions options) + : DbContext(options) { protected override void OnConfiguring(DbContextOptionsBuilder builder) { diff --git a/test/TestBuildingBlocks/XUnitLogHttpMessageHandler.cs b/test/TestBuildingBlocks/XUnitLogHttpMessageHandler.cs new file mode 100644 index 0000000000..4b981f81d2 --- /dev/null +++ b/test/TestBuildingBlocks/XUnitLogHttpMessageHandler.cs @@ -0,0 +1,76 @@ +using Microsoft.Extensions.Logging; +using Xunit.Abstractions; + +namespace TestBuildingBlocks; + +/// +/// Writes incoming and outgoing HTTP messages to the test output window. +/// +public sealed partial class XUnitLogHttpMessageHandler : DelegatingHandler +{ + private static readonly string BodySeparator = $"{Environment.NewLine}{Environment.NewLine}"; + private readonly LoggerFactory _loggerFactory; + private readonly ILogger _logger; + + public XUnitLogHttpMessageHandler(ITestOutputHelper testOutputHelper) + { + ArgumentNullException.ThrowIfNull(testOutputHelper); + +#pragma warning disable CA2000 // Dispose objects before losing scope + // Justification: LoggerFactory.AddProvider takes ownership (passing the provider as a constructor parameter does not). + var loggerProvider = new XUnitLoggerProvider(testOutputHelper, null, LogOutputFields.Message); +#pragma warning restore CA2000 // Dispose objects before losing scope + + _loggerFactory = new LoggerFactory(); + _loggerFactory.AddProvider(loggerProvider); + + _logger = _loggerFactory.CreateLogger(); + } + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + if (_logger.IsEnabled(LogLevel.Debug)) + { + string? requestBody = request.Content == null ? null : await request.Content.ReadAsStringAsync(cancellationToken); + + if (!string.IsNullOrEmpty(requestBody)) + { + LogRequestMessage(request.ToString(), BodySeparator, requestBody); + } + else + { + LogRequestMessage(request.ToString(), string.Empty, string.Empty); + } + } + + HttpResponseMessage response = await base.SendAsync(request, cancellationToken); + + if (_logger.IsEnabled(LogLevel.Debug)) + { + string responseBody = await response.Content.ReadAsStringAsync(cancellationToken); + + if (!string.IsNullOrEmpty(responseBody)) + { + LogResponseMessage(response.ToString(), BodySeparator, responseBody); + } + else + { + LogResponseMessage(response.ToString(), string.Empty, string.Empty); + } + } + + return response; + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + _loggerFactory.Dispose(); + } + + [LoggerMessage(Level = LogLevel.Debug, SkipEnabledCheck = true, Message = "--> {RequestMessage}{Separator}{RequestBody}")] + private partial void LogRequestMessage(string requestMessage, string separator, string requestBody); + + [LoggerMessage(Level = LogLevel.Debug, SkipEnabledCheck = true, Message = "<-- {ResponseMessage}{Separator}{ResponseBody}")] + private partial void LogResponseMessage(string responseMessage, string separator, string responseBody); +} diff --git a/test/TestBuildingBlocks/XUnitLoggerProvider.cs b/test/TestBuildingBlocks/XUnitLoggerProvider.cs index 6b5e7f93ec..26c15d575b 100644 --- a/test/TestBuildingBlocks/XUnitLoggerProvider.cs +++ b/test/TestBuildingBlocks/XUnitLoggerProvider.cs @@ -1,5 +1,4 @@ using System.Text; -using JsonApiDotNetCore; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Xunit.Abstractions; @@ -9,13 +8,14 @@ namespace TestBuildingBlocks; // Based on https://www.meziantou.net/how-to-get-asp-net-core-logs-in-the-output-of-xunit-tests.htm. public sealed class XUnitLoggerProvider : ILoggerProvider { + private const LogOutputFields DefaultLogOutputFields = LogOutputFields.All & ~LogOutputFields.CategoryNamespace; private readonly ITestOutputHelper _testOutputHelper; private readonly LogOutputFields _outputFields; private readonly string? _categoryPrefixFilter; - public XUnitLoggerProvider(ITestOutputHelper testOutputHelper, string? categoryPrefixFilter, LogOutputFields outputFields = LogOutputFields.All) + public XUnitLoggerProvider(ITestOutputHelper testOutputHelper, string? categoryPrefixFilter, LogOutputFields outputFields = DefaultLogOutputFields) { - ArgumentGuard.NotNull(testOutputHelper); + ArgumentNullException.ThrowIfNull(testOutputHelper); _testOutputHelper = testOutputHelper; _categoryPrefixFilter = categoryPrefixFilter; @@ -24,7 +24,7 @@ public XUnitLoggerProvider(ITestOutputHelper testOutputHelper, string? categoryP public ILogger CreateLogger(string categoryName) { - ArgumentGuard.NotNull(categoryName); + ArgumentException.ThrowIfNullOrEmpty(categoryName); if (_categoryPrefixFilter == null || categoryName.StartsWith(_categoryPrefixFilter, StringComparison.Ordinal)) { @@ -42,7 +42,34 @@ private sealed class XUnitLogger(ITestOutputHelper testOutputHelper, LogOutputFi { private readonly ITestOutputHelper _testOutputHelper = testOutputHelper; private readonly LogOutputFields _outputFields = outputFields; - private readonly string _categoryName = categoryName; + private readonly string? _categoryText = GetCategoryText(categoryName, outputFields); + + private static string? GetCategoryText(string categoryName, LogOutputFields outputFields) + { + if (outputFields.HasFlag(LogOutputFields.Category)) + { + return categoryName; + } + + bool hasName = outputFields.HasFlag(LogOutputFields.CategoryName); + bool hasNamespace = outputFields.HasFlag(LogOutputFields.CategoryNamespace); + + if (hasName || hasNamespace) + { + // Microsoft.Extensions.Logging.LoggerFactory.CreateLogger(Type) removes generic type parameters + // and replaces '+' (nested class) with '.'. + int lastDotIndex = categoryName.LastIndexOf('.'); + + if (lastDotIndex == -1) + { + return hasName ? categoryName : string.Empty; + } + + return hasName ? categoryName[(lastDotIndex + 1)..] : categoryName[..lastDotIndex]; + } + + return null; + } public bool IsEnabled(LogLevel logLevel) { @@ -69,7 +96,7 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except builder.Append(logLevelString); } - if (_outputFields.HasFlag(LogOutputFields.Category)) + if (_categoryText != null) { if (builder.Length > 0) { @@ -77,7 +104,7 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except } builder.Append('['); - builder.Append(_categoryName); + builder.Append(_categoryText); builder.Append(']'); } diff --git a/test/UnitTests/Graph/Implementation.cs b/test/UnitTests/Graph/Implementation.cs index e098482049..c53e559379 100644 --- a/test/UnitTests/Graph/Implementation.cs +++ b/test/UnitTests/Graph/Implementation.cs @@ -1,3 +1,6 @@ +using JetBrains.Annotations; + namespace UnitTests.Graph; +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] internal sealed class Implementation : IGenericInterface; diff --git a/test/UnitTests/Graph/ResourceDescriptorAssemblyCacheTests.cs b/test/UnitTests/Graph/ResourceDescriptorAssemblyCacheTests.cs index 8f30b584e4..0531c42b1a 100644 --- a/test/UnitTests/Graph/ResourceDescriptorAssemblyCacheTests.cs +++ b/test/UnitTests/Graph/ResourceDescriptorAssemblyCacheTests.cs @@ -1,7 +1,6 @@ using FluentAssertions; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Resources; -using TestBuildingBlocks; using Xunit; namespace UnitTests.Graph; @@ -21,7 +20,7 @@ public void GetResourceDescriptorsPerAssembly_Locates_Identifiable_Resource() IReadOnlyCollection descriptors = assemblyCache.GetResourceDescriptors(); // Assert - descriptors.ShouldNotBeEmpty(); + descriptors.Should().NotBeEmpty(); descriptors.Should().ContainSingle(descriptor => descriptor.ResourceClrType == resourceClrType); } @@ -38,7 +37,7 @@ public void GetResourceDescriptorsPerAssembly_Only_Contains_IIdentifiable_Types( IReadOnlyCollection descriptors = assemblyCache.GetResourceDescriptors(); // Assert - descriptors.ShouldNotBeEmpty(); + descriptors.Should().NotBeEmpty(); descriptors.Select(descriptor => descriptor.ResourceClrType).Should().AllBeAssignableTo(); } } diff --git a/test/UnitTests/Graph/TypeLocatorTests.cs b/test/UnitTests/Graph/TypeLocatorTests.cs index 7f5ed820d8..2731dcba0a 100644 --- a/test/UnitTests/Graph/TypeLocatorTests.cs +++ b/test/UnitTests/Graph/TypeLocatorTests.cs @@ -1,7 +1,6 @@ using System.Reflection; using FluentAssertions; using JsonApiDotNetCore.Configuration; -using TestBuildingBlocks; using Xunit; namespace UnitTests.Graph; @@ -22,27 +21,9 @@ public void GetContainerRegistrationFromAssembly_Gets_Implementation() (Type implementationType, Type serviceInterface)? result = typeLocator.GetContainerRegistrationFromAssembly(assembly, unboundInterface, typeArgument); // Assert - result.ShouldNotBeNull(); - result.Value.implementationType.Should().Be(typeof(Implementation)); - result.Value.serviceInterface.Should().Be(typeof(IGenericInterface)); - } - - [Fact] - public void GetDerivedTypesForUnboundType_Gets_Implementation() - { - // Arrange - Assembly assembly = GetType().Assembly; - Type unboundType = typeof(BaseType<>); - Type typeArgument = typeof(int); - - var typeLocator = new TypeLocator(); - - // Act - IReadOnlyCollection results = typeLocator.GetDerivedTypesForUnboundType(assembly, unboundType, typeArgument); - - // Assert - results.ShouldHaveCount(1); - results.ElementAt(0).Should().Be(typeof(DerivedType)); + result.Should().NotBeNull(); + result.Value.implementationType.Should().Be(); + result.Value.serviceInterface.Should().Be>(); } [Fact] @@ -57,7 +38,7 @@ public void GetIdType_Correctly_Identifies_JsonApiResource() Type? idType = typeLocator.LookupIdType(type); // Assert - idType.Should().Be(typeof(int)); + idType.Should().Be(); } [Fact] @@ -87,9 +68,9 @@ public void ResolveResourceDescriptor_Returns_Type_If_Type_Is_IIdentifiable() ResourceDescriptor? descriptor = typeLocator.ResolveResourceDescriptor(resourceClrType); // Assert - descriptor.ShouldNotBeNull(); + descriptor.Should().NotBeNull(); descriptor.ResourceClrType.Should().Be(resourceClrType); - descriptor.IdClrType.Should().Be(typeof(int)); + descriptor.IdClrType.Should().Be(); } [Fact] diff --git a/test/UnitTests/Models/IdentifiableTests.cs b/test/UnitTests/Models/IdentifiableTests.cs index 993a3988f2..ad11081c65 100644 --- a/test/UnitTests/Models/IdentifiableTests.cs +++ b/test/UnitTests/Models/IdentifiableTests.cs @@ -33,7 +33,7 @@ public void GetStringId_Returns_Null_If_Object_Is_Default() { var resource = new IntId(); - string? stringId = resource.ExposedGetStringId(default); + string? stringId = resource.ExposedGetStringId(0); stringId.Should().BeNull(); } diff --git a/test/UnitTests/Models/ResourceConstructionExpressionTests.cs b/test/UnitTests/Models/ResourceConstructionExpressionTests.cs index 277af5f013..48e43d2452 100644 --- a/test/UnitTests/Models/ResourceConstructionExpressionTests.cs +++ b/test/UnitTests/Models/ResourceConstructionExpressionTests.cs @@ -2,9 +2,7 @@ using System.Linq.Expressions; using FluentAssertions; using JetBrains.Annotations; -using JsonApiDotNetCore; using JsonApiDotNetCore.Resources; -using TestBuildingBlocks; using Xunit; namespace UnitTests.Models; @@ -15,7 +13,8 @@ public sealed class ResourceConstructionExpressionTests public void When_resource_has_default_constructor_it_must_succeed() { // Arrange - var factory = new ResourceFactory(new ServiceContainer()); + using var serviceProvider = new ServiceContainer(); + var factory = new ResourceFactory(serviceProvider); // Act NewExpression newExpression = factory.CreateNewExpression(typeof(ResourceWithoutConstructor)); @@ -24,14 +23,15 @@ public void When_resource_has_default_constructor_it_must_succeed() Func createFunction = Expression.Lambda>(newExpression).Compile(); ResourceWithoutConstructor resource = createFunction(); - resource.ShouldNotBeNull(); + resource.Should().NotBeNull(); } [Fact] public void When_resource_has_constructor_with_string_parameter_it_must_fail() { // Arrange - var factory = new ResourceFactory(new ServiceContainer()); + using var serviceProvider = new ServiceContainer(); + var factory = new ResourceFactory(serviceProvider); // Act Action action = () => factory.CreateNewExpression(typeof(ResourceWithStringConstructor)); @@ -50,7 +50,7 @@ private sealed class ResourceWithStringConstructor : Identifiable public ResourceWithStringConstructor(string text) { - ArgumentGuard.NotNullNorEmpty(text); + ArgumentException.ThrowIfNullOrEmpty(text); Text = text; } diff --git a/test/UnitTests/UnitTests.csproj b/test/UnitTests/UnitTests.csproj index 99fc7ce781..68076a51e1 100644 --- a/test/UnitTests/UnitTests.csproj +++ b/test/UnitTests/UnitTests.csproj @@ -1,6 +1,6 @@ - net8.0;net6.0 + net9.0;net8.0 diff --git a/tests.runsettings b/tests.runsettings index db83eb983e..e6790c9356 100644 --- a/tests.runsettings +++ b/tests.runsettings @@ -1,5 +1,8 @@ + + true + true @@ -7,7 +10,9 @@ - ObsoleteAttribute,GeneratedCodeAttribute + **/test/**/*.* + [*]JsonApiDotNetCore.OpenApi.JsonApiObjects.* + ObsoleteAttribute,GeneratedCodeAttribute,TestSDKAutoGeneratedCode true